/******************************************************************************/ /* Copyright (c) 2016 MD Automotive Controls. Original Work. */ /* License: http://www.gnu.org/licenses/gpl.html GPL version 2 or higher */ /******************************************************************************/ /* CONTEXT:KERNEL */ /* PACKAGE TITLE: TEPM */ /* DESCRIPTION: Timed Event Programs module provides services for the */ /* output of timed pulse-trains */ /* FILE NAME: TEPM.c */ /* REVISION HISTORY: 19-08-2016 | 1.0 | Initial revision */ /* */ /******************************************************************************/ #define _TEPM_C #include #include "build.h" #include "CEM.h" #include "client.h" #include "CPUAbstract.h" #include "CQUEUE.h" #include "declarations.h" #include "stddef.h" #include "types.h" #include "IRQ.h" #include "TEPM.h" #include "TEPMHA.h" #include "TEPMAPI.h" #include "MSG.h" #include "SIM.h" #include "REGSET.h" #include "RESM.h" #include "IOAPI.h" #include "SYSAPI.h" //#define DEBUG_TEPM /* Private data declarations -------------------------*/ TEPMAPI_tstTimedUserEvent TEPM_aastTimedUserEvents[TEPMHA_nEventChannels][TEPMHA_nUserEventsMax]; TEPMAPI_tstTimedKernelEvent TEPM_aastTimedKernelEvents[TEPMHA_nEventChannels][TEPMHA_nKernelEventsMax]; const TEPM_tstTEPMChannel TEPM_rastTEPMChannel[] = TEPMHA_nChannelInfo; const IOAPI_tenEHIOResource TEPM_rastTEPMFastChannel[] = TEPMHA_nChannelFastInfo; const TEPM_tstMasters TEPM_rastMasters[] = TEPMHA_nMasterInfo; CQUEUE_tstQueue TEPM_astProgramKernelQueue[TEPMHA_nEventChannels]; CQUEUE_tstQueue TEPM_astProgramUserQueue[TEPMHA_nEventChannels]; TEPMAPI_tpfEventCB TEPM_atpfEventKernelCB[TEPMHA_nEventChannels]; TEPMAPI_tpfEventCB TEPM_atpfEventUserCB[TEPMHA_nEventChannels]; TEPM_tstTEPMResult TEPM_astEventResult[TEPMHA_nEventChannels]; MSG_tstMBX* TEPM_apstMBX[TEPMHA_nEventChannels]; bool TEPM_aboTEPMChannelModeInput[TEPMHA_nEventChannels]; bool TEPM_aboTEPMChannelModeOutput[TEPMHA_nEventChannels]; bool TEPM_aboTEPMChannelModeRecursive[TEPMHA_nEventChannels]; bool TEPM_au32TEPMChannelRecursionCount[TEPMHA_nEventChannels]; bool TEPM_aboTEPMChannelModePWM[TEPMHA_nEventChannels]; bool TEPM_aboTEPMChannelAsyncRequestEnable[TEPMHA_nEventChannels]; uint32 TEPM_au32TEPMChannelSequence[TEPMHA_nEventChannels]; bool TEPM_aboSynchroniseEnable[TEPMHA_nEventChannels]; volatile bool TEPM_aboQueueOverflow[TEPMHA_nEventChannels]; EXTERN uint32 CAM_u32RPMRaw; EXTERN IOAPI_tenEdgePolarity CEM_enEdgePolarity; bool TEPM_boDisableSequences; IOAPI_tenEHIOResource TEPM_astTEPMVVTInputs[4]; IOAPI_tenEHIOResource TEPM_astTEPMLinkedResource[TEPMHA_nEventChannels]; uint32 TEPM_u32PrimaryPhaseIDX; uint16 TEPM_au16PWMLowResidual[16]; uint32 TEPM_u32FuelCutsPercent; uint32 TEPM_u32SparkCutsPercent; uint32 TEPM_u32FuelCutsMask; uint32 TEPM_u32SparkCutsMask; uint32 TEPM_u32FuelChannelCount; uint32 TEPM_u32SparkChannelCount; uint32 TEPM_u32FuelCutsCounter; #ifdef TEPM_PRIO_INPUT_MK6X extern const TEPM_tstTEPMReverseChannel TEPMHA_rastTEPMReverseChannel[]; #endif //TEPM_PRIO_INPUT_MK6X #define TEPM_nTableCount sizeof(TEPM_rastTEPMChannel) / sizeof(TEPM_tstTEPMChannel) /* Private function declarations ----------------------------*/ #ifdef TEPM_USER_MODE static void TEPM_vRunEventProgramUserQueue(void*, uint32, uint32); #endif //TEPM_USER_MODE static void TEPM_vRunEventProgramKernelQueue(void*, uint32, uint32, uint32, bool); static void* TEPM_pvGetModule(IOAPI_tenEHIOResource); static void* TEPM_pstGetModuleFromEnum(TEPMHA_tenTimerModule); static uint32 TEPM_u32GetTimerHardwareChannel(IOAPI_tenEHIOResource); /* Public function definitions ---------------------------*/ void TEPM_vStart(puint32 const pu32Arg) { uint32 u32QueueIDX; for (u32QueueIDX = 0; u32QueueIDX < TEPMHA_nEventChannels; u32QueueIDX++) { CQUEUE_xInit(TEPM_astProgramUserQueue + u32QueueIDX, TEPMHA_nUserEventsMax, (uint32)TEPM_aastTimedUserEvents + u32QueueIDX * TEPMHA_nUserEventsMax * sizeof(TEPMAPI_tstTimedUserEvent)); CQUEUE_xInit(TEPM_astProgramKernelQueue + u32QueueIDX, TEPMHA_nKernelEventsMax, (uint32)TEPM_aastTimedKernelEvents + u32QueueIDX * TEPMHA_nUserEventsMax * sizeof(TEPMAPI_tstTimedKernelEvent)); TEPM_atpfEventKernelCB[u32QueueIDX] = NULL; TEPM_atpfEventUserCB[u32QueueIDX] = NULL; TEPM_apstMBX[u32QueueIDX] = NULL; TEPM_aboTEPMChannelModeInput[u32QueueIDX] = FALSE; TEPM_aboTEPMChannelModeOutput[u32QueueIDX] = FALSE; TEPM_aboTEPMChannelAsyncRequestEnable[u32QueueIDX] = FALSE; TEPM_au32TEPMChannelSequence[u32QueueIDX] = ~0; TEPM_boDisableSequences = FALSE; TEPM_astTEPMLinkedResource[u32QueueIDX] = EH_IO_Invalid; } TEPM_u32FuelCutsPercent = 5; } IOAPI_tenEHIOResource TEPM_enGetPrimaryLinkedResource(void) { return TEPM_astTEPMLinkedResource[TEPM_u32PrimaryPhaseIDX]; } void TEPM_vAsyncRequest(void) { CEM_u32GlobalCycleFraction = 0x0000; TEPM_vStartEventProgramKernelQueues(TRUE, 0); CEM_u32GlobalCycleFraction += (0x10000 / CEM_u32SyncPoints); TEPM_vStartEventProgramKernelQueues(TRUE, 1); CEM_u32GlobalCycleFraction = 0x10000; TEPM_vStartEventProgramKernelQueues(TRUE, 4); CEM_u32GlobalCycleFraction += (0x10000 / CEM_u32SyncPoints); TEPM_vStartEventProgramKernelQueues(TRUE, 5); } void TEPM_vEnableSequences(bool boEnable) { TEPM_boDisableSequences = ~boEnable; } void TEPM_vRun(puint32 const pu32Arg) { /* static uint32 u32Count; uint32 u32TimerChannelIDX; void* pvModule; const IOAPI_tenEHIOResource raenResourceList[] = TEPMHA_nChannelResourceList; uint32 u32ChannelIDX; IOAPI_tenEHIOResource enEHIOResource; TEPMAPI_ttEventTime tEventTimeScheduled; u32Count++; if (0 == (u32Count % 50)) { for (u32TimerChannelIDX = 0; u32TimerChannelIDX < TEPMHA_nEventChannels; u32TimerChannelIDX++) { if (TRUE == TEPM_aboTEPMChannelModePWM[u32TimerChannelIDX]) { enEHIOResource = raenResourceList[u32TimerChannelIDX]; uint32 u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); CPU_xEnterCritical(); tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + 50; tEventTimeScheduled &= TEPMHA_nCounterMask; TEPMHA_vCapComAction(TEPMAPI_enSetHigh, pvModule, u32ChannelIDX, 0, tEventTimeScheduled); CPU_xExitCritical(); } } } if (1 == (u32Count % 50)) { for (u32TimerChannelIDX = 0; u32TimerChannelIDX < TEPMHA_nEventChannels; u32TimerChannelIDX++) { if (TRUE == TEPM_aboTEPMChannelModePWM[u32TimerChannelIDX]) { enEHIOResource = raenResourceList[u32TimerChannelIDX]; uint32 u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); CPU_xEnterCritical(); tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); tEventTimeScheduled += ((*TEPM_aastTimedKernelEvents[u32TableIDX][0].ptEventTime)); tEventTimeScheduled &= TEPMHA_nCounterMask; TEPMHA_vCapComAction(TEPMAPI_enSetLow, pvModule, u32ChannelIDX, 0, tEventTimeScheduled); CPU_xExitCritical(); } } } */ } void TEPM_vTerminate(puint32 const pu32Arg) { } uint32 TEPM_u32InitTEPMChannel(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_tstTEPMChannelCB* pstTEPMChannelCB, bool boPWMMode) { //uint32 u32ChannelIDX; uint32 u32TableIDX; //uint32 u32ControlWord = 0; MSG_tenMBXErr enMBXErr; TEPMHA_vInitTEPMChannel(enEHIOResource, pstTEPMChannelCB); u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); TEPM_astTEPMLinkedResource[u32TableIDX] = pstTEPMChannelCB->enLinkedResource; if ((pstTEPMChannelCB->enAction == TEPMAPI_enCapAny) | (pstTEPMChannelCB->enAction == TEPMAPI_enCapRising) | (pstTEPMChannelCB->enAction == TEPMAPI_enCapFalling)) { TEPM_aboTEPMChannelModeInput[u32TableIDX] = TRUE; TEPM_aboTEPMChannelModeOutput[u32TableIDX] = FALSE; TEPM_aboTEPMChannelModeRecursive[u32TableIDX] = pstTEPMChannelCB->boRecursive; } else { TEPM_aboTEPMChannelModeOutput[u32TableIDX] = TRUE; TEPM_aboTEPMChannelModeInput[u32TableIDX] = FALSE; TEPM_aboTEPMChannelModePWM[u32TableIDX] = boPWMMode; TEPM_aboTEPMChannelModeRecursive[u32TableIDX] = FALSE; } if (0x10000000 <= pstTEPMChannelCB->u32Sequence) { /* Special case for VVT input MS 8bit = 0x10 */ TEPM_au32TEPMChannelSequence[u32TableIDX] = pstTEPMChannelCB->u32Sequence; } else if (0x10000 <= pstTEPMChannelCB->u32Sequence) { /* Special case for fuel pressure control solenoid MS 16bit != 0*/ TEPM_au32TEPMChannelSequence[u32TableIDX] = (pstTEPMChannelCB->u32Sequence & 0xf) + ((pstTEPMChannelCB->u32Sequence & 0xf00) >> 4) + ((pstTEPMChannelCB->u32Sequence & 0xf0000) >> 8) + ((pstTEPMChannelCB->u32Sequence & 0xf000000) >> 12) + 0x04000000; } else if ((0x00000080 <= pstTEPMChannelCB->u32Sequence) && (0x000000FF >= pstTEPMChannelCB->u32Sequence)) { /* Special case for fuel pressure control solenoid Golf MK6 16bit != 0*/ TEPM_au32TEPMChannelSequence[u32TableIDX] = (pstTEPMChannelCB->u32Sequence & 0xff) + 0x08000000; } else { TEPM_au32TEPMChannelSequence[u32TableIDX] = pstTEPMChannelCB->u32Sequence & 0xffff; if (((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0x0ff) == 0x0ff) || ((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xff00) == 0xff00)) { TEPM_au32TEPMChannelSequence[u32TableIDX] |= 0x02000000; } else { TEPM_au32TEPMChannelSequence[u32TableIDX] |= 0x01000000; } } TEPM_aboTEPMChannelAsyncRequestEnable[u32TableIDX] = pstTEPMChannelCB->boAsyncRequestEnable; /* Check if a mailbox is allocated for this table index */ if (NULL == TEPM_apstMBX[u32TableIDX]) { enMBXErr = MSG_enMBXNew((MSG_tstMBX**)&TEPM_apstMBX[u32TableIDX], MSG_enTEPMEvent); } /* TODO suppress warning */ (void)enMBXErr; return TEPM_rastTEPMChannel[u32TableIDX].u32MuxSel; } SYSAPI_tenSVCResult TEPM_vInitTEPMResource(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_tstTEPMResourceCB* pstTEPMResourceCB) { return TEPMHA_vInitTEPMResource(enEHIOResource, pstTEPMResourceCB); } void TEPM_boGetMasterEHIOResourceList(IOAPI_tenEHIOResource enEHIOResource, IOAPI_tenEHIOResource* penEHIOResource, puint32 pu32MasterCount) { uint32 u32ChannelIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); uint32 u32MasterIDX = 0; while ((RESM_nMastersMax > *pu32MasterCount) && (TEPMHA_nMastersMax > u32MasterIDX)) { if (NULL != TEPM_rastMasters[u32ChannelIDX].enEHIOResource[u32MasterIDX]) { *penEHIOResource = TEPM_rastMasters[u32ChannelIDX].enEHIOResource[u32MasterIDX]; penEHIOResource++; (*pu32MasterCount)++; u32MasterIDX++; } } } void TEPM_vAppendTEPMQueue(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_tstTimedUserEvent* pstTimedEvents, TEPMAPI_ttEventCount tEventCount) { uint32 u32TableIDX; CPU_xEnterCritical(); u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); while ((0 < tEventCount--) && (FALSE == CQUEUE_xIsFull(TEPM_astProgramUserQueue + u32TableIDX))) { memcpy((void*)&TEPM_aastTimedUserEvents[u32TableIDX][TEPM_astProgramUserQueue[u32TableIDX].u32Tail], (void*)pstTimedEvents++, sizeof(TEPMAPI_tstTimedUserEvent)); CQUEUE_xAddItem(TEPM_astProgramUserQueue + u32TableIDX); } CPU_xExitCritical(); } void TEPM_vConfigureUserTEPMInput(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_tstTimedUserEvent* pstTimedEvent) { uint32 u32TableIDX; u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); switch (pstTimedEvent->enMethod) { case TEPMAPI_enLinkPrimaryProgram: { TEPM_atpfEventKernelCB[u32TableIDX] = &CEM_vPrimaryEventCB; TEPM_u32PrimaryPhaseIDX = u32TableIDX; break; } case TEPMAPI_enLinkVVT1Input: { TEPM_atpfEventKernelCB[u32TableIDX] = &CEM_vPhaseEventCB; TEPM_astTEPMVVTInputs[0] = enEHIOResource; break; } case TEPMAPI_enLinkVVT2Input: { TEPM_atpfEventKernelCB[u32TableIDX] = &CEM_vPhaseEventCB; TEPM_astTEPMVVTInputs[1] = enEHIOResource; break; } case TEPMAPI_enLinkVVT3Input: { TEPM_atpfEventKernelCB[u32TableIDX] = &CEM_vPhaseEventCB; TEPM_astTEPMVVTInputs[2] = enEHIOResource; break; } case TEPMAPI_enLinkVVT4Input: { TEPM_atpfEventKernelCB[u32TableIDX] = &CEM_vPhaseEventCB; TEPM_astTEPMVVTInputs[3] = enEHIOResource; break; } case TEPMAPI_enLinkFreqInput: { TEPM_atpfEventKernelCB[u32TableIDX] = & CEM_vFreqEventCB; break; } default: { break; } } TEPM_atpfEventUserCB[u32TableIDX] = pstTimedEvent->pfEventCB; if (FALSE == CQUEUE_xIsFull(TEPM_astProgramUserQueue + u32TableIDX)) { memcpy((void*)&TEPM_aastTimedUserEvents[u32TableIDX][TEPM_astProgramUserQueue[u32TableIDX].u32Tail], (void*)pstTimedEvent, sizeof(TEPMAPI_tstTimedUserEvent)); CQUEUE_xAddItem(TEPM_astProgramUserQueue + u32TableIDX); } } void TEPM_vConfigureKernelTEPMOutput(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_tstTimedKernelEvent* pstTimedEvents, TEPMAPI_ttEventCount tEventCount) { uint32 u32TableIDX; u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); TEPM_atpfEventUserCB[u32TableIDX] = pstTimedEvents->pfEventCB; /* Reset the queue count it is not possible to append a Kernel output queue */ CQUEUE_xClearCount(TEPM_astProgramKernelQueue + u32TableIDX); while ((0 < tEventCount--) && (FALSE == CQUEUE_xIsFull(TEPM_astProgramKernelQueue + u32TableIDX))) { memcpy((void*)&TEPM_aastTimedKernelEvents[u32TableIDX][TEPM_astProgramKernelQueue[u32TableIDX].u32Tail], (void*)pstTimedEvents++, sizeof(TEPMAPI_tstTimedKernelEvent)); CQUEUE_xAddItem(TEPM_astProgramKernelQueue + u32TableIDX); } } void TEPM_vInitiateUserCallBack(IOAPI_tenEHIOResource enEHIOResource, TEPMAPI_ttEventTime tEventTime) { MSG_tstMBX* pstMBX; tpfClientCB pfClientCB; CLIENT_tenErr enErr; uint32 u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); /* Store the programmed event resource for the user callback */ TEPM_astEventResult[u32TableIDX].enEHIOResource = enEHIOResource; /* Store the timer result for the user callback */ TEPM_astEventResult[u32TableIDX].tEventTime = tEventTime; pfClientCB = (tpfClientCB)TEPM_atpfEventUserCB[u32TableIDX]; pstMBX = TEPM_apstMBX[u32TableIDX]; MSG_vMBXPost(pstMBX, (void*)&TEPM_astEventResult[u32TableIDX]); if ((NULL != pfClientCB) && (MSG_boMBXValid(pstMBX))) { enErr = CLIENT_enEnqueueCB(pstMBX, pfClientCB); } /* TODO suppress warning */ (void)enErr; } void TEPM_u32GetFreeVal(IOAPI_tenEHIOResource enEHIOResource, puint32 pu32Data) { void* pvModule = TEPM_pvGetModule(enEHIOResource); TEPMHA_vGetFreeVal(pvModule, pu32Data); } void TEPM_vInterruptHandler(IOAPI_tenEHIOResource enEHVIOResource, void* pvData) { uint32 u32ChannelIDX; uint32 u32TableIDX; uint32 u32Flags = 0; uint32 u32Temp; TEPMAPI_tpfEventCB pfTEPMEventCB; uint32 u32StartChannelIDX = 0; uint32 u32EndChannelIDX; IOAPI_tenEHIOResource enEHIOResource; static uint32 u32FalseAlarmCount; TEPMAPI_ttEventTime tEventTimeScheduled; #ifdef TEPM_PRIO_INPUT_MK6X static uint32 u32PrioChannelIDX = TEPMHA_nPRIOCHANNEL; #endif //TEPM_PRIO_INPUT_MK6X /* Note here the resource passed in is the timer module resource not the timer channel */ void* pvModule = TEPMHA_pvGetTimerModuleFromVIO(enEHVIOResource); #ifndef TEPM_SPEED_MK6X u32StartChannelIDX = 0; #endif //TEPM_SPEED_MK6X u32EndChannelIDX = u32StartChannelIDX + TEPMHA_u32GetTimerChannelsPerInterruptGroup(pvModule); /* Loop through the channels contained within this interrupt group */ for (u32ChannelIDX = u32StartChannelIDX; u32ChannelIDX < u32EndChannelIDX; u32ChannelIDX++) { #ifdef TEPM_SPEED_MK6X if (FTM_CnSC_CHF_MASK == (FTM_CnSC_CHF_MASK & ((tstTimerModule*)pvModule)->CONTROLS[u32ChannelIDX].CnSC)) #else if (true == TEPMHA_boFlagIsSet(pvModule, u32ChannelIDX, &u32Flags, u32Sequence[u32Prio], u32Prio)) #endif //TEPM_SPEED_MK6X { #ifdef TEPM_SPEED_MK6X if (FTM_CnSC_CHIE_MASK == (FTM_CnSC_CHIE_MASK & ((tstTimerModule*)pvModule)->CONTROLS[u32ChannelIDX].CnSC)) #else if (true == TEMPHA_boInterruptEnabled(pvModule, u32ChannelIDX)) #endif //TEPM_SPEED_MK6X { #ifndef TEPM_SPEED_MK6X enEHIOResource = TEPMHA_enGetTimerResourceFromVIOAndIndex(enEHVIOResource, u32ChannelIDX); u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); #else u32Temp = 8 * ((uint32)(enEHVIOResource - EH_VIO_FTM0)) + u32ChannelIDX; enEHIOResource = TEPMHA_rastTEPMReverseChannel[u32Temp].enEHIOResource; u32TableIDX = enEHIOResource - EH_IO_TMR1; #endif //TEPM_SPEED_MK6X if (TRUE == TEPM_aboTEPMChannelModeOutput[u32TableIDX]) { if (TRUE == TEPM_aboTEPMChannelModePWM[u32TableIDX]) { pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); if (0 == TEPM_au16PWMLowResidual[u32TableIDX]) { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0); u32Temp = (*TEPM_aastTimedKernelEvents[u32TableIDX][0].ptEventTime); u32Temp *= TEPM_aastTimedKernelEvents[u32TableIDX][0].tAccumulate; u32Temp /= 0x10000; tEventTimeScheduled += u32Temp; tEventTimeScheduled &= TEPMHA_nCounterMask; TEPMHA_vCapComAction(TEPMAPI_enSetLow, pvModule, u32ChannelIDX, 0, tEventTimeScheduled); TEPM_au16PWMLowResidual[u32TableIDX] = TEPM_aastTimedKernelEvents[u32TableIDX][0].tAccumulate - u32Temp; } else { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0); tEventTimeScheduled += TEPM_au16PWMLowResidual[u32TableIDX]; tEventTimeScheduled &= TEPMHA_nCounterMask; TEPMHA_vCapComAction(TEPMAPI_enSetHigh, pvModule, u32ChannelIDX, 0, tEventTimeScheduled); TEPM_au16PWMLowResidual[u32TableIDX] = 0; } } else { if (TRUE == TEPM_aboQueueOverflow[u32TableIDX]) { TEPM_aboQueueOverflow[u32TableIDX] = FALSE; CQUEUE_xSetHead(TEPM_astProgramKernelQueue + u32TableIDX, 0); TEPM_vStartEventProgramKernelQueues(FALSE, TEPM_au32TEPMChannelSequence[u32TableIDX]); } else if (FALSE == TEPMHA_boCheckFalseAlarm(pvModule, u32ChannelIDX, TEPMHA_u32GetTimerHardwareSubChannel(u32TableIDX))) { TEPM_vRunEventProgramKernelQueue(pvModule, u32ChannelIDX, u32TableIDX, TEPM_au32TEPMChannelSequence[u32TableIDX], false); TEPM_vInitiateUserCallBack(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); } else { u32FalseAlarmCount++; } } } else if (TRUE == TEPM_aboTEPMChannelModeInput[u32TableIDX]) { pfTEPMEventCB = TEPM_atpfEventKernelCB[u32TableIDX]; if (NULL != pfTEPMEventCB) { #if defined (TEPM_REENTRANCY) IOAPI_tenTriState enPrioTriState; IOAPI_tenTriState enPrioTriStateOld; bool boHWReentrancy = FALSE; bool boHWReentrancyFlag = FALSE; if (TRUE == TEPM_aboTEPMChannelModeRecursive[u32TableIDX]) { if (0 == TEPM_au32TEPMChannelRecursionCount[u32TableIDX]) { /* Let's go again */ TEMPHA_vResetTimerFlag(pvModule, u32ChannelIDX); TEPM_au32TEPMChannelRecursionCount[u32TableIDX]++; pfTEPMEventCB(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); } else { TEPM_au32TEPMChannelRecursionCount[u32TableIDX]++; } if (0 != TEPM_au32TEPMChannelRecursionCount[u32TableIDX]) { TEPM_au32TEPMChannelRecursionCount[u32TableIDX]--; } } else #endif //TEPM_REENTRANCY { pfTEPMEventCB(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); #ifdef TEPM_REENTRANCY_HW IOAPI_tenTriState enPrioTriState; IOAPI_tenTriState enPrioTriStateOld; bool boHWReentrancy = FALSE; bool boHWReentrancyFlag = FALSE; if (u32PrioChannelIDX == u32ChannelIDX) { if (IOAPI_enEdgeFalling == CEM_enEdgePolarity) { /* But HW inverted */ enPrioTriStateOld = IOAPI_enHigh; enPrioTriState = TEPM_enGetTimerDigitalState(TEPM_PRIO_RESOURCE); } else { /* But HW inverted */ enPrioTriStateOld = IOAPI_enLow; enPrioTriState = TEPM_enGetTimerDigitalState(TEPM_PRIO_RESOURCE); } boHWReentrancy = TRUE; boHWReentrancyFlag = FALSE; } #endif //TEPM_REENTRANCY_HW } } } } TEMPHA_vResetTimerFlag(pvModule, u32ChannelIDX); } #ifdef TEPM_PRIO_INPUT_MK6X #ifdef TEPM_SPEED_MK6X if ((u32PrioChannelIDX < u32EndChannelIDX) && (FTM_CnSC_CHIE_MASK == (FTM_CnSC_CHIE_MASK & ((tstTimerModule*)pvModule)->CONTROLS[u32ChannelIDX].CnSC))) #else if ((u32PrioChannelIDX < u32EndChannelIDX) && (true == TEMPHA_boInterruptEnabled(pvModule, u32PrioChannelIDX))) #endif //TEPM_SPEED_MK6X { #ifndef TEPM_SPEED_MK6X enEHIOResource = TEPMHA_enGetTimerResourceFromVIOAndIndex(enEHVIOResource, u32PrioChannelIDX); u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); #else u32Temp = 8 * ((uint32)(enEHVIOResource - EH_VIO_FTM0)) + u32PrioChannelIDX; enEHIOResource = TEPMHA_rastTEPMReverseChannel[u32Temp].enEHIOResource; u32TableIDX = enEHIOResource - EH_IO_TMR1; #endif //TEPM_SPEED_MK6X if (TRUE == TEPM_aboTEPMChannelModeInput[u32TableIDX]) { #if defined (TEPM_REENTRANCY_HW) if (TRUE == boHWReentrancy) { /* Sanity check edge polarity */ if (IOAPI_enEdgeFalling == CEM_enEdgePolarity) { enPrioTriState = TEPM_enGetTimerDigitalState(enEHIOResource); /* Invert the polarity because the circuit inverts */ if (enPrioTriState != enPrioTriStateOld) { if (IOAPI_enHigh == enPrioTriState) { boHWReentrancyFlag = TRUE; } } enPrioTriStateOld = enPrioTriState;//move up } } #endif //TEPM_RENTRANCY_HW if (FTM_CnSC_CHF_MASK == (FTM_CnSC_CHF_MASK & ((tstTimerModule*)pvModule)->CONTROLS[u32PrioChannelIDX].CnSC)) { pfTEPMEventCB = TEPM_atpfEventKernelCB[u32TableIDX]; #if defined (TEPM_REENTRANCY) if (IOAPI_enEdgeFalling == CEM_enEdgePolarity) { /* But HW inverted */ enPrioTriStateOld = IOAPI_enHigh; enPrioTriState = TEPM_enGetTimerDigitalState(TEPM_PRIO_RESOURCE); } else { /* But HW inverted */ enPrioTriStateOld = IOAPI_enLow; enPrioTriState = TEPM_enGetTimerDigitalState(TEPM_PRIO_RESOURCE); } boHWReentrancy = TRUE; boHWReentrancyFlag = FALSE; #endif //TEPM_REENTRANCY if (NULL != pfTEPMEventCB) { #if defined (TEPM_REENTRANCY) if (TRUE == TEPM_aboTEPMChannelModeRecursive[u32TableIDX]) { if (0 == TEPM_au32TEPMChannelRecursionCount[u32TableIDX]) { /* Let's go again */ TEMPHA_vResetTimerFlag(pvModule, u32PrioChannelIDX); TEPM_au32TEPMChannelRecursionCount[u32TableIDX]++; pfTEPMEventCB(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32PrioChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); } else { TEPM_au32TEPMChannelRecursionCount[u32TableIDX]++; } if (0 != TEPM_au32TEPMChannelRecursionCount[u32TableIDX]) { TEPM_au32TEPMChannelRecursionCount[u32TableIDX]--; } } else #endif //TEPM_REENTRANCY { #if defined (TEPM_REENTRANCY_HW) //boHWReentrancy = FALSE; #endif //TEPM_REENTRANCY_HW pfTEPMEventCB(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32PrioChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); } } TEMPHA_vResetTimerFlag(pvModule, u32PrioChannelIDX); } #if defined (TEPM_REENTRANCY_HW) else if (TRUE == boHWReentrancyFlag) { pfTEPMEventCB = TEPM_atpfEventKernelCB[u32TableIDX]; if (NULL != pfTEPMEventCB) { boHWReentrancyFlag = FALSE; pfTEPMEventCB(enEHIOResource, TEPMHA_tGetScheduledVal(pvModule, u32PrioChannelIDX, TEPM_aboTEPMChannelModeInput[u32TableIDX], u32Flags)); } } #endif //TEPM_REENTRANCY_HW } } #endif //TEPM_PRIO_INPUT_MK6X } } IOAPI_tenTriState TEPM_enGetTimerDigitalState(IOAPI_tenEHIOResource enEHIOResource) { return TEPMHA_enGetTimerDigitalState(enEHIOResource); } /* Private function definitions ---------------------------*/ #ifdef TEPM_USER_MODE static void TEPM_vRunEventProgramUserQueue(void* pvModule, uint32 u32ChannelIDX, uint32 u32TableIDX) { TEPMAPI_tstTimedUserEvent* pstTimedEvent; TEPMAPI_ttEventTime tEventTimeScheduled; TEPMAPI_ttEventTime tEventTimeRemains; if (FALSE == (CQUEUE_xIsEmpty(TEPM_astProgramUserQueue + u32TableIDX))) { pstTimedEvent = &TEPM_aastTimedUserEvents[u32TableIDX][TEPM_astProgramUserQueue[u32TableIDX].u32Head]; switch (pstTimedEvent->enMethod) { case TEPMAPI_enHardAlarm: { if (0x7ff0 > pstTimedEvent->tEventTime) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + pstTimedEvent->tEventTime; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); if ((0x10 > tEventTimeRemains) || (0x8000 < tEventTimeRemains)) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + 0x80; } } else { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + pstTimedEvent->tEventTime; } break; } case TEPMAPI_enHardLinkedTimeStep: { if (0x7ff0 > pstTimedEvent->tEventTime) { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0) + pstTimedEvent->tEventTime; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); if ((0x10 > tEventTimeRemains) || (0x8000 < tEventTimeRemains)) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + 0x80; } } else { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0) + pstTimedEvent->tEventTime; } break; } default: { break; } } //TEPMHA_vCapComAction(pstTimedEvent->enAction, pvModule, u32ChannelIDX, 0, tEventTimeScheduled); TEPM_atpfEventUserCB[u32TableIDX] = pstTimedEvent->pfEventCB; CQUEUE_xRemoveItem(TEPM_astProgramUserQueue + u32TableIDX); } else { #ifdef TEPM_REMOVE_RESIDUAL_INTERRUPTS /* The queue is empty therefore this was a next window interrupt so go ahead and disable interrupts */ TEPMHA_vDisconnectEnable(pvModule, u32ChannelIDX); #endif } } #endif //TEPM_USER_MODE void TEPM_vStartEventProgramKernelQueues(bool boAsyncRequest, uint32 u32SequenceIDX) { IOAPI_tenEHIOResource enEHIOResource; void* pvModule; uint32 u32ChannelIDX; uint32 u32SubChannelIDX; const IOAPI_tenEHIOResource raenResourceList[] = TEPMHA_nChannelResourceList; uint32 u32TimerChannelIDX; uint32 u32TableIDX; static uint32 u32SyncRPMLimit = 6000; bool boSyncProceed = false; if (TRUE == boAsyncRequest) { CEM_u32GlobalCycleTime = 0x8000; } for (u32TimerChannelIDX = 0; u32TimerChannelIDX < TEPMHA_nEventChannels; u32TimerChannelIDX++) { enEHIOResource = raenResourceList[u32TimerChannelIDX]; #ifndef TEPM_SPEED_MK6X u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); #else u32TableIDX = enEHIOResource - EH_IO_TMR1; #endif //TEPM_SPEED_MK6X if ((TRUE == TEPM_aboTEPMChannelModeOutput[u32TableIDX]) && (FALSE == TEPM_aboTEPMChannelModePWM[u32TableIDX])) { if (0x04 == (TEPM_au32TEPMChannelSequence[u32TableIDX] >> 24)) { if ((u32SequenceIDX == (TEPM_au32TEPMChannelSequence[u32TableIDX] & 0x0f)) || (u32SequenceIDX == ((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xf0) >> 4)) || (u32SequenceIDX == ((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xf00) >> 8)) || (u32SequenceIDX == ((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xf000) >> 12))) { boSyncProceed = true; } } else if (0x08 == (TEPM_au32TEPMChannelSequence[u32TableIDX] >> 24)) { if (u32SequenceIDX == (TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xff)) { boSyncProceed = true; } } else { if ((u32SequenceIDX == (TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xff)) || (u32SequenceIDX == ((TEPM_au32TEPMChannelSequence[u32TableIDX] & 0xff00) >> 8))) { boSyncProceed = true; } } } if (true == boSyncProceed) { TEPM_aboSynchroniseEnable[u32TimerChannelIDX] = u32SyncRPMLimit < CAM_u32RPMRaw ? FALSE : TRUE; if (((TRUE == TEPM_aboTEPMChannelAsyncRequestEnable[u32TableIDX]) && (TRUE == boAsyncRequest)) || (FALSE == boAsyncRequest)) { //if ((TRUE == CQUEUE_xIsEmpty(TEPM_astProgramKernelQueue + u32TableIDX)) && // (TRUE == CQUEUE_xIsStaticActive(TEPM_astProgramKernelQueue + u32TableIDX))) /* EMPTY TEST MAYBE NOT REQUIRED */ if ((TRUE == CQUEUE_xIsEmpty(TEPM_astProgramKernelQueue + u32TableIDX)) && (TRUE == CQUEUE_xIsStaticActive(TEPM_astProgramKernelQueue + u32TableIDX)) && (FALSE == CQUEUE_xIsAtStaticHead(TEPM_astProgramKernelQueue + u32TableIDX))) { pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); u32SubChannelIDX = TEPMHA_u32GetTimerHardwareSubChannel(u32TableIDX); /* Queue didn't end normally last cycle */ TEPMHA_vForceQueueTerminate(pvModule, u32ChannelIDX, u32SubChannelIDX); CQUEUE_xResetStaticHead(TEPM_astProgramKernelQueue + u32TableIDX); //TEPM_aboQueueOverflow[u32TableIDX] = TRUE; } if (FALSE == CQUEUE_xIsEmpty(TEPM_astProgramKernelQueue + u32TableIDX) && TRUE == CQUEUE_xIsAtStaticHead(TEPM_astProgramKernelQueue + u32TableIDX)) { /* This queue is populated and head is at zero (static head) */ pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); TEPM_vRunEventProgramKernelQueue(pvModule, u32ChannelIDX, u32TableIDX, u32SequenceIDX, false); TEPM_aboQueueOverflow[u32TimerChannelIDX] = FALSE; } } boSyncProceed = false; } } } void TEPM_vGetTimerVal(IOAPI_tenEHIOResource enEHIOResource, puint32 pu32Val) { *pu32Val = TEPMHA_u32GetTimerVal(enEHIOResource); } void TEPM_vSynchroniseEventProgramKernelQueues(void) { IOAPI_tenEHIOResource enEHIOResource; void* pvModule; const IOAPI_tenEHIOResource raenResourceList[] = TEPMHA_nChannelResourceList; uint32 u32ChannelIDX; uint32 u32TimerChannelIDX; for (u32TimerChannelIDX = 0; u32TimerChannelIDX < TEPMHA_nEventChannels; u32TimerChannelIDX++) { enEHIOResource = raenResourceList[u32TimerChannelIDX]; uint32 u32TableIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); if (FALSE == CQUEUE_xIsEmpty(TEPM_astProgramKernelQueue + u32TableIDX) && (FALSE == CQUEUE_xIsAtStaticHead(TEPM_astProgramKernelQueue + u32TableIDX)) && (TRUE == TEPM_aboTEPMChannelModeOutput[u32TableIDX])) { /* If not at static head which means queue is done and reset */ pvModule = TEPMHA_pvGetModuleFromEnum(TEPM_rastTEPMChannel[u32TableIDX].enModule); u32ChannelIDX = TEPM_u32GetTimerHardwareChannel(enEHIOResource); TEPM_vRunEventProgramKernelQueue(pvModule, u32ChannelIDX, u32TableIDX, TEPM_au32TEPMChannelSequence[u32TableIDX], true); } } } static void TEPM_vRunEventProgramKernelQueue(void* pvModule, uint32 u32ChannelIDX, uint32 u32TableIDX, uint32 u32SequenceIDX, bool boSynchroniseUpdate) { TEPMAPI_tstTimedKernelEvent* pstTimedEvent = NULL; TEPMAPI_ttEventTime tEventTimeScheduled; TEPMAPI_ttEventTime tEventTimeRemains; uint32 u32Temp; uint32 u32ModulePhaseCorrect = 0; uint32 u32SubChannelIDX; volatile bool boSynchroniseAbort = FALSE; uint32 u32GlobalSequenceFraction; uint32 u32EventTime; TEPMAPI_tstTimedKernelEvent stTempKernelEvent; /* Mask out the sequence index alternate origin index and windows span */ u32SequenceIDX &= 0xff; #define DEBUG_TEPM_OFF #ifdef DEBUG_TEPM static volatile uint32 test[32]; static uint32 test_idx; #endif if (FALSE == CQUEUE_xIsEmpty(TEPM_astProgramKernelQueue + u32TableIDX)) { if (TRUE == boSynchroniseUpdate) { if (1 == TEPM_astProgramKernelQueue[u32TableIDX].u32Head) { /* If waiting for first event, let's look at it */ pstTimedEvent = &TEPM_aastTimedKernelEvents[u32TableIDX][TEPM_astProgramKernelQueue[u32TableIDX].u32Head - 1]; switch (pstTimedEvent->enMethod) { case TEPMAPI_enGlobalLinkedFraction: { if (FALSE == TEPM_aboSynchroniseEnable[u32TableIDX]) { /* Not eligible for a synchronise so abort */ pstTimedEvent = NULL; } break; } default: { /* Not eligible for a synchronise so abort */ pstTimedEvent = NULL; } } } } else { pstTimedEvent = &TEPM_aastTimedKernelEvents[u32TableIDX][TEPM_astProgramKernelQueue[u32TableIDX].u32Head]; } if (NULL != pstTimedEvent) { u32SubChannelIDX = TEPMHA_u32GetTimerHardwareSubChannel(u32TableIDX); /* Timed event pointer is NULL for a failed synchronise */ switch (pstTimedEvent->enMethod) { case TEPMAPI_enGlobalLinkedFraction: { #ifdef DEBUG_TEPM test[test_idx] = CEM_u32GlobalCycleTime; test_idx++; if (test_idx == 0x20) { test_idx = 0; } #endif u32ModulePhaseCorrect = TEPMHA_u32GetModulePhaseCorrect(TEPMHA_enTimerEnumFromModule(pvModule), u32ChannelIDX); if (1 == (TEPM_au32TEPMChannelSequence[u32TableIDX] >> 24)) { u32GlobalSequenceFraction = 0xffff & (CEM_u32GlobalCycleFraction - (u32SequenceIDX * 0x10000 / CEM_u32SyncPoints)); /* Divide global cycle time by 8 for scale again by phase repeats this might be half global window */ u32Temp = CEM_u32GlobalCycleTime / (TEPMHA_nCounterGlobalDiv * CEM_u8PhaseRepeats); } else if (2 == (TEPM_au32TEPMChannelSequence[u32TableIDX] >> 24)) { u32GlobalSequenceFraction = 0xffff & ((CEM_u32GlobalCycleFraction >> 1) - (u32SequenceIDX * 0x8000 / CEM_u32SyncPoints)); /* Divide global cycle time by TEPMHA_nCounterGlobalDiv for scale */ u32Temp = CEM_u32GlobalCycleTime / TEPMHA_nCounterGlobalDiv; } else { u32GlobalSequenceFraction = 0; /* Divide global cycle time by TEPMHA_nCounterGlobalDiv for scale */ u32Temp = CEM_u32GlobalCycleTime / (2 * TEPMHA_nCounterGlobalDiv * CEM_u8PhaseRepeats); } if (u32GlobalSequenceFraction < *(pstTimedEvent->ptEventTime)) { if (((0 == u32GlobalSequenceFraction) && (FALSE == boSynchroniseUpdate)) || (TRUE == boSynchroniseUpdate)) { u32Temp *= (*(pstTimedEvent->ptEventTime) - u32GlobalSequenceFraction); u32Temp = u32Temp / (0x10000 / TEPMHA_nCounterGlobalDiv); u32Temp = TEPMHA_nLongestDelay < u32Temp ? TEPMHA_nLongestDelay : u32Temp; tEventTimeScheduled = CEM_tSyncTimeLast + u32ModulePhaseCorrect + u32Temp; tEventTimeScheduled &= TEPMHA_nCounterMask; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); tEventTimeRemains &= TEPMHA_nCounterMask; if (FALSE == boSynchroniseUpdate) { if ((TEPM_nSoonCounts > tEventTimeRemains) || ((TEPMHA_nCounterMask - TEPM_nSoonCounts) < tEventTimeRemains)) //if (TEPM_nSoonCountsLoose > tEventTimeRemains) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + TEPM_nSoonCountsLoose; tEventTimeScheduled &= TEPMHA_nCounterMask; } } else { if ((TEPM_nSoonCounts > tEventTimeRemains) || ((TEPMHA_nCounterMask - TEPM_nSoonCounts) < tEventTimeRemains)) { boSynchroniseAbort = TRUE; } } } else { boSynchroniseAbort = TRUE; } } else { boSynchroniseAbort = TRUE; } break; } case TEPMAPI_enGlobalLinkedTimeStep: { u32ModulePhaseCorrect = TEPMHA_u32GetModulePhaseCorrect(TEPMHA_enTimerEnumFromModule(pvModule), u32ChannelIDX); if (FALSE == boSynchroniseUpdate) { u32Temp = *(pstTimedEvent->ptEventTime); tEventTimeScheduled = CEM_tSyncTimeLast + u32ModulePhaseCorrect + u32Temp; tEventTimeScheduled &= TEPMHA_nCounterMask; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); tEventTimeRemains &= TEPMHA_nCounterMask; if ((TEPM_nSoonCounts > tEventTimeRemains) || ((TEPMHA_nCounterMask - TEPM_nSoonCounts) < tEventTimeRemains)) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + TEPM_nSoonCounts; tEventTimeScheduled &= TEPMHA_nCounterMask; } } else { boSynchroniseAbort = TRUE; } break; } case TEPMAPI_enGlobalLinkedFractionStep: { u32Temp = CEM_u32GlobalCycleTime / 2; u32Temp *= *(pstTimedEvent->ptEventTime); u32Temp = MIN(0x7fc00000, u32Temp); u32Temp /= 0x8000; tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0) + u32Temp; tEventTimeScheduled &= TEPMHA_nCounterMask; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); if ((TEPM_nSoonCounts > tEventTimeRemains) || (-TEPM_nSoonCounts < tEventTimeRemains)) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + TEPM_nSoonCounts; tEventTimeScheduled &= TEPMHA_nCounterMask; } break; } case TEPMAPI_enHardLinkedTimeStep: { if (0 != pstTimedEvent->ptAccumulate) { if (*(pstTimedEvent->ptEventTime) > (*pstTimedEvent->ptAccumulate - pstTimedEvent->tAccumulate)) { u32EventTime = *pstTimedEvent->ptAccumulate - pstTimedEvent->tAccumulate; memcpy(&stTempKernelEvent, pstTimedEvent, sizeof(stTempKernelEvent)); pstTimedEvent = &stTempKernelEvent; pstTimedEvent->enAction = TEPMAPI_enSetLow; TEPM_astProgramKernelQueue[u32TableIDX].u32Head = TEPM_astProgramKernelQueue[u32TableIDX].u32Tail - 1; } else { u32EventTime = *(pstTimedEvent->ptEventTime); } } else { u32EventTime = *(pstTimedEvent->ptEventTime); } if (-TEPM_nSoonCounts > *(pstTimedEvent->ptEventTime)) { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0) + u32EventTime; tEventTimeScheduled &= TEPMHA_nCounterMask; tEventTimeRemains = tEventTimeScheduled - TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX); if ((TEPM_nSoonCounts > tEventTimeRemains) || (-TEPM_nSoonCounts < tEventTimeRemains)) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + TEPM_nSoonCounts; tEventTimeScheduled &= TEPMHA_nCounterMask; } } else { tEventTimeScheduled = TEPMHA_tGetScheduledVal(pvModule, u32ChannelIDX, FALSE, 0) + u32EventTime; } break; } default: { break; } } if (FALSE == boSynchroniseAbort) { if (FALSE == TEPM_boDisableSequences) { if (TEPMAPI_enSetLow == pstTimedEvent->enAction) { if (0 != (TEPM_u32FuelCutsMask & MATH_u32IDXToMask(u32TableIDX))) { TEPM_u32FuelCutsCounter = (TEPM_u32FuelCutsCounter + 1) % 5; if (5 > TEPM_u32FuelCutsPercent) { if (TEPM_u32FuelCutsPercent <= TEPM_u32FuelCutsCounter) { tEventTimeScheduled = TEPMHA_u32GetFreeVal(pvModule, u32ChannelIDX) + TEPM_nSoonCountsLoose; tEventTimeScheduled &= TEPMHA_nCounterMask; } } } } TEPMHA_vCapComAction(pstTimedEvent->enAction, pvModule, u32ChannelIDX, u32SubChannelIDX, tEventTimeScheduled); if (EH_IO_Invalid != pstTimedEvent->enEHIOBitMirrorResource) { if (TEPMAPI_enSetLow == pstTimedEvent->enAction) { IO_vAssertDIOResource(pstTimedEvent->enEHIOBitMirrorResource, IOAPI_enHigh); } } } else { TEPMHA_vCapComAction(TEPMAPI_enSetLow, pvModule, u32ChannelIDX, u32SubChannelIDX, tEventTimeScheduled); } } if (FALSE == boSynchroniseUpdate) { TEPM_atpfEventUserCB[u32TableIDX] = pstTimedEvent->pfEventCB; if (0 != pstTimedEvent->ptAccumulate) { /* Accumulate time into next event */ pstTimedEvent[1].tAccumulate = pstTimedEvent->tAccumulate + *(pstTimedEvent->ptEventTime); } CQUEUE_xRemoveItem(TEPM_astProgramKernelQueue + u32TableIDX); } } } else if (FALSE == boSynchroniseUpdate) { if (TRUE == CQUEUE_xIsStaticActive(TEPM_astProgramKernelQueue + u32TableIDX)) { CQUEUE_xResetStaticHead(TEPM_astProgramKernelQueue + u32TableIDX); pstTimedEvent = &TEPM_aastTimedKernelEvents[u32TableIDX][0]; if (EH_IO_Invalid != pstTimedEvent->enEHIOBitMirrorResource) { IO_vAssertDIOResource(pstTimedEvent->enEHIOBitMirrorResource, IOAPI_enLow); } } /* The queue is empty so go ahead and disable interrupts and connection */ TEPMHA_vDisconnectEnable(pvModule, u32ChannelIDX); } } static void* TEPM_pvGetModule(IOAPI_tenEHIOResource enEHIOResource) { uint32 u32ChannelIDX; void* pvModule; u32ChannelIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); pvModule = TEPM_pstGetModuleFromEnum(TEPM_rastTEPMChannel[u32ChannelIDX].enModule); return pvModule; } static void* TEPM_pstGetModuleFromEnum(TEPMHA_tenTimerModule enTimerModule) { return TEPMHA_pvGetModuleFromEnum(enTimerModule); } static uint32 TEPM_u32GetTimerHardwareChannel(IOAPI_tenEHIOResource enEHIOResource) { uint32 u32ChannelIDX; u32ChannelIDX = TEPMHA_u32GetFTMTableIndex(enEHIOResource); return TEPM_rastTEPMChannel[u32ChannelIDX].u32Channel; } uint32 TEPM_u32GetFTMTableIndex(IOAPI_tenEHIOResource enEHIOResource) { return TEPMHA_u32GetFTMTableIndex(enEHIOResource); } uint32 TEPM_u32GetTimerVal(IOAPI_tenEHIOResource enEHIOResource, void* pvData) { return 0; } void TEPM_vSetFuelCutsMask(uint32 u32CutsPercent, uint32 u32CutsMask, uint32 u32ChannelCount) { TEPM_u32FuelCutsPercent = 5 - (u32CutsPercent / 20); TEPM_u32FuelCutsMask = u32CutsMask; TEPM_u32FuelChannelCount = u32ChannelCount; } void TEPM_vSetSparkCutsMask(uint32 u32CutsPercent, uint32 u32CutsMask, uint32 u32ChannelCount) { TEPM_u32SparkCutsPercent = 5 - (u32CutsPercent / 20); TEPM_u32SparkCutsMask = u32CutsMask; TEPM_u32SparkChannelCount = u32ChannelCount; }