/*================================================================================================== * Project : RTD AUTOSAR 4.4 * Platform : CORTEXM * Peripheral : Stm_Pit_Rtc_Emios * Dependencies : none * * Autosar Version : 4.4.0 * Autosar Revision : ASR_REL_4_4_REV_0000 * Autosar Conf.Variant : * SW Version : 0.9.0 * Build Version : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326 * * (c) Copyright 2020 - 2021 NXP Semiconductors * All Rights Reserved. * * NXP Confidential. This software is owned or controlled by NXP and may only be * used strictly in accordance with the applicable license terms. By expressly * accepting such terms or by downloading, installing, activating and/or otherwise * using the software, you are agreeing that you have read, and that you agree to * comply with and are bound by, such license terms. If you do not agree to be * bound by the applicable license terms, then you may not retain, install, * activate or otherwise use the software. ==================================================================================================*/ /** * @file Pit_Ip.c * * @addtogroup pit_ip Pit IPL * * @{ */ #ifdef __cplusplus extern "C"{ #endif /*================================================================================================== * INCLUDE FILES * 1) system and project includes * 2) needed interfaces from external units * 3) internal and external interfaces from this unit ==================================================================================================*/ #include "Pit_Ip.h" #ifdef PIT_IP_ENABLE_USER_MODE_SUPPORT #define USER_MODE_REG_PROT_ENABLED PIT_IP_ENABLE_USER_MODE_SUPPORT #include "RegLockMacros.h" #endif /*================================================================================================== * SOURCE FILE VERSION INFORMATION ==================================================================================================*/ #define PIT_IP_VENDOR_ID_C 43 #define PIT_IP_AR_RELEASE_MAJOR_VERSION_C 4 #define PIT_IP_AR_RELEASE_MINOR_VERSION_C 4 #define PIT_IP_AR_RELEASE_REVISION_VERSION_C 0 #define PIT_IP_SW_MAJOR_VERSION_C 0 #define PIT_IP_SW_MINOR_VERSION_C 9 #define PIT_IP_SW_PATCH_VERSION_C 0 /*================================================================================================== * FILE VERSION CHECKS ==================================================================================================*/ #if (PIT_IP_VENDOR_ID != PIT_IP_VENDOR_ID_C) #error "Pit_Ip.h and Pit_Ip.c have different vendor ids" #endif /* Check if header file and Gpt header file are of the same Autosar version */ #if ((PIT_IP_AR_RELEASE_MAJOR_VERSION != PIT_IP_AR_RELEASE_MAJOR_VERSION_C) || \ (PIT_IP_AR_RELEASE_MINOR_VERSION != PIT_IP_AR_RELEASE_MINOR_VERSION_C) || \ (PIT_IP_AR_RELEASE_REVISION_VERSION != PIT_IP_AR_RELEASE_REVISION_VERSION_C) \ ) #error "AutoSar Version Numbers of Pit_Ip.h and Pit_Ip.c are different" #endif /* Check if source file and GPT header file are of the same Software version */ #if ((PIT_IP_SW_MAJOR_VERSION != PIT_IP_SW_MAJOR_VERSION_C) || \ (PIT_IP_SW_MINOR_VERSION != PIT_IP_SW_MINOR_VERSION_C) || \ (PIT_IP_SW_PATCH_VERSION != PIT_IP_SW_PATCH_VERSION_C) \ ) #error "Software Version Numbers of Pit_Ip.h and Pit_Ip.c are different" #endif #ifdef PIT_IP_ENABLE_USER_MODE_SUPPORT #ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK #if ((REGLOCKMACROS_AR_RELEASE_MAJOR_VERSION != PIT_IP_AR_RELEASE_MAJOR_VERSION_C) || \ (REGLOCKMACROS_AR_RELEASE_MINOR_VERSION != PIT_IP_AR_RELEASE_MINOR_VERSION_C)) #error "AutoSar Version Numbers of RegLockMacros.h and Pit_Ip.c are different" #endif #endif #endif /*================================================================================================== * LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS) ==================================================================================================*/ /*================================================================================================= * LOCAL MACROS =================================================================================================*/ /*================================================================================================== * LOCAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * LOCAL VARIABLES ==================================================================================================*/ #if (PIT_IP_USED == STD_ON) #if (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) #define GPT_START_SEC_VAR_NO_INIT_BOOLEAN #include "Gpt_MemMap.h" /** * @brief Pit_Ip_bIsChangedTimeout * @details Local variable used to check that whether this channel called ChangeNextTimeout. */ static boolean Pit_Ip_bIsChangedTimeout; #define GPT_STOP_SEC_VAR_NO_INIT_BOOLEAN #include "Gpt_MemMap.h" #endif /* (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) */ /*================================================================================================== * GLOBAL CONSTANTS ==================================================================================================*/ /*================================================================================================== * GLOBAL VARIABLES ==================================================================================================*/ #if (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) #define GPT_START_SEC_VAR_NO_INIT_32 #include "Gpt_MemMap.h" /** * @brief Pit_Ip_u32OldTargetValue * @details Local variable used to store the previous target time value after call ChangeNextTimeout. */ uint32 Pit_Ip_u32OldTargetValue; #define GPT_STOP_SEC_VAR_NO_INIT_32 #include "Gpt_MemMap.h" #endif /* (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) */ #define GPT_START_SEC_CONST_UNSPECIFIED #include "Gpt_MemMap.h" /** @brief Table of base addresses for PIT instances. */ PIT_Type * const pitBase[PIT_INSTANCE_COUNT] = PIT_BASE_PTRS; #define GPT_STOP_SEC_CONST_UNSPECIFIED #include "Gpt_MemMap.h" #define GPT_START_SEC_VAR_INIT_UNSPECIFIED #include "Gpt_MemMap.h" #if ((defined PIT_0_ISR_USED)||(defined PIT_1_ISR_USED)||(defined PIT_2_ISR_USED)) /** @brief Global array variable used to channel state for process common interrupt */ static Pit_Ip_State Pit_Ip_u32ChState[PIT_INSTANCE_COUNT][PIT_CHANNEL_COUNT] = { { { (boolean)FALSE, #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) NULL_PTR, #endif NULL_PTR, 0U } } }; #endif #define GPT_STOP_SEC_VAR_INIT_UNSPECIFIED #include "Gpt_MemMap.h" /*================================================================================================== * LOCAL FUNCTION PROTOTYPES ==================================================================================================*/ #define GPT_START_SEC_CODE #include "Gpt_MemMap.h" #if (PIT_IP_MODULE_SINGLE_INTERRUPT == STD_ON) #ifdef PIT_0_ISR_USED ISR(PIT_0_ISR); #endif #ifdef PIT_1_ISR_USED ISR(PIT_1_ISR); #endif #ifdef PIT_2_ISR_USED ISR(PIT_2_ISR); #endif #endif /*PIT_IP_MODULE_SINGLE_INTERRUPT == STD_ON*/ #if ((defined PIT_0_ISR_USED)||(defined PIT_1_ISR_USED)||(defined PIT_2_ISR_USED)) static void Pit_Ip_ProcessCommonInterrupt(uint8 instance, uint8 channel); static inline uint32 Pit_Ip_GetInterruptBit(uint8 instance, uint8 channel); #endif static inline void Pit_Ip_EnableModule(uint8 instance, uint8 timerType); static inline void Pit_Ip_Reset(uint8 instance, uint8 channelNum, boolean available); static inline void Pit_Ip_EnableTimer(uint8 instance, uint8 channel, boolean enable); static inline void Pit_Ip_SetDebugMode(uint8 instance, boolean stopRun); static inline void Pit_Ip_SetChainMode(uint8 instance, uint8 channel, boolean enable); static inline boolean Pit_Ip_IsChannelRunning(uint8 instance, uint8 channel); static inline void Pit_Ip_SetCounterValue(uint8 instance, uint8 channel, uint32 value); static inline uint32 Pit_Ip_GetCounterValue(uint8 instance, uint8 channel); static inline void Pit_Ip_EnableInterrupt(uint8 instance, uint8 channel, boolean enable); static inline void Pit_Ip_ClearInterruptFlag(uint8 instance, uint8 channel); static inline uint32 Pit_Ip_GetUpperLifetimerValue(uint8 instance); static inline uint32 Pit_Ip_GetLowerLifetimerValue(uint8 instance); #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) static void Pit_Ip_StartTimeout(uint32 *startTimeOut, uint32 *elapsedTimeOut, uint32 *timeoutTicksOut, uint32 timeoutUs); static boolean Pit_Ip_TimeoutExpired(uint32 *startTimeInOut, uint32 *elapsedTimeInOut, uint32 timeoutTicks); #if (PIT_IP_REPORT_ERROR_STATUS == STD_ON) void Pit_Ip_ErrorReport(void); #endif #endif #if (STD_ON == PIT_IP_ENABLE_USER_MODE_SUPPORT) void Pit_Ip_SetUserAccessAllowed(uint32 PitBaseAddr); #endif #if (defined(MCAL_PIT_REG_PROT_AVAILABLE) && (STD_ON == PIT_IP_ENABLE_USER_MODE_SUPPORT)) #define Call_Pit_Ip_SetUserAccessAllowed(PitBaseAddr) OsIf_Trusted_Call1param(Pit_Ip_SetUserAccessAllowed,(PitBaseAddr)) #else #define Call_Pit_Ip_SetUserAccessAllowed(PitBaseAddr) #endif #ifdef MCAL_PIT_REG_PROT_AVAILABLE /** * @brief Enables PIT registers writing in User Mode by configuring REG_PROT * @details Sets the UAA (User Access Allowed) bit of the PIT IP allowing PIT registers writing in User Mode * * @param[in] none * * @return none * * @pre Should be executed in supervisor mode * @post none */ void Pit_Ip_SetUserAccessAllowed (uint32 PitBaseAddr) { SET_USER_ACCESS_ALLOWED(PitBaseAddr, PIT_PROT_MEM_U32); } #endif /* MCAL_PIT_REG_PROT_AVAILABLE */ /*================================================================================================== * LOCAL FUNCTIONS ==================================================================================================*/ /** * @brief Pit_Ip_GetLoadValue * @details Support get load value PIT * This register is intended for Timer Load Value * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * * @return periodValue * @pre The driver needs to be initialized. */ uint32 Pit_Ip_GetLoadValue(uint8 instance, uint8 channel) { uint32 periodValue = 0U; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { periodValue = pitBase[instance]->RTI_LDVAL; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ periodValue = pitBase[instance]->TIMER[channel].LDVAL; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ return periodValue; } /** * @brief Pit_Ip_GetInterruptFlags * @details Support PIT interrupt flags * This register is intended for Timer Interrupt Flag * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return returnFlag * @pre The driver needs to be initialized. */ uint32 Pit_Ip_GetInterruptFlags(uint8 instance, uint8 channel) { uint32 returnFlag = 0U; #ifdef PIT_RTI_CHANNEL_EXISTS if (RTI == channel) { returnFlag = ((pitBase[instance]->RTI_TFLG & PIT_RTI_TFLG_TIF_MASK) >> PIT_RTI_TFLG_TIF_SHIFT); } else #endif { returnFlag = ((pitBase[instance]->TIMER[channel].TFLG & PIT_TFLG_TIF_MASK) >> PIT_TFLG_TIF_SHIFT); } return returnFlag; } /** * @brief Pit_Ip_EnableModule * @details Support Pit enable module. * This register is intended for PIT Module Control. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw instance number * @param[in] enable TRUE/FALSE * * @return void * @pre The driver needs to be initialized.Enable/disable chain mode. */ static inline void Pit_Ip_EnableModule(uint8 instance, uint8 timerType) { if (0U == timerType) { pitBase[instance]->MCR &= ~PIT_MCR_MDIS_MASK; } #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) else { pitBase[instance]->MCR &= ~PIT_MCR_MDIS_RTI_MASK; } #endif } /** * @brief Pit_Ip_EnableTimer * @details Support enable timer. * This register is intended for Timer Control * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw instance number * @param[in] enable TRUE/FALSE * * @return void * @pre The driver needs to be initialized.Enable/disable chain mode. */ static inline void Pit_Ip_EnableTimer(uint8 instance, uint8 channel, boolean enable) { SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_00(); { if ((boolean)TRUE == enable) { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_TCTRL |= PIT_RTI_TCTRL_TEN_MASK; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].TCTRL |= PIT_TCTRL_TEN_MASK; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } else { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_TCTRL &= ~PIT_RTI_TCTRL_TEN_MASK; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].TCTRL &= ~PIT_TCTRL_TEN_MASK; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } } SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_00(); } /** * @brief Pit_Ip_SetDebugMode * @details This register enables or disables the PIT timer clocks and controls the timers * when the PIT enters the Debug mode. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw instance number * @param[in] stopRun * * @return void * @pre The driver needs to be initialized.Enable/disable debug mode. */ static inline void Pit_Ip_SetDebugMode(uint8 instance, boolean stopRun) { if ((boolean)TRUE == stopRun) { pitBase[instance]->MCR |= PIT_MCR_FRZ_MASK; } else { pitBase[instance]->MCR &= ~PIT_MCR_FRZ_MASK; } } /** * @brief Pit_Ip_SetChainMode * @details Support chain mode * This register is intended for Timer Control * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw instance number * @param[in] enable TRUE/FALSE * * @return void * @pre The driver needs to be initialized.Enable/disable chain mode. */ static inline void Pit_Ip_SetChainMode(uint8 instance, uint8 channel, boolean enable) { SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_01(); { if (((boolean)TRUE == enable) && (channel > 0U)) { pitBase[instance]->TIMER[channel].TCTRL |= PIT_TCTRL_CHN_MASK; } else { pitBase[instance]->TIMER[channel].TCTRL &= ~PIT_TCTRL_CHN_MASK; } } SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_01(); } /** * @brief Pit_Ip_Reset * @details Support reset * This register is intended for PIT Module Control * * @param[in] instance PIT hw instance number * @param[in] channelNum PIT hw channel number * * * @return void * @pre The driver needs to be initialized. */ static inline void Pit_Ip_Reset(uint8 instance, uint8 channelNum, boolean available) { uint32 mask = 0U; uint32 channelIndex = channelNum; if((boolean)TRUE == available) { channelIndex = channelIndex -1U; #ifdef PIT_RTI_CHANNEL_EXISTS pitBase[instance]->RTI_TCTRL = PIT_RTI_TCTRL_TEN(0U) | PIT_RTI_TCTRL_TIE(0U); pitBase[instance]->RTI_LDVAL = PIT_RTI_LDVAL_TSV(0U); pitBase[instance]->RTI_TFLG = PIT_RTI_TFLG_TIF_MASK; mask = PIT_MCR_MDIS(1U) | PIT_MCR_FRZ(0U) | PIT_MCR_MDIS_RTI(1U); #endif } else { mask = PIT_MCR_MDIS(1U) | PIT_MCR_FRZ(0U); } for (uint8 i = 0U; i < channelIndex; i++) { pitBase[instance]->TIMER[i].TCTRL = PIT_TCTRL_TEN(0U) | PIT_TCTRL_TIE(0U) | PIT_TCTRL_CHN(0U); pitBase[instance]->TIMER[i].LDVAL = PIT_LDVAL_TSV(0U); pitBase[instance]->TIMER[i].TFLG = PIT_TFLG_TIF_MASK; } pitBase[instance]->MCR = mask; } /** * @brief Pit_Ip_IsChannelRunning * @details Support enable/disable Timer Enable * This register is intended for Timer Control Register * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * * * @return isRunning * @pre The driver needs to be initialized. * */ static inline boolean Pit_Ip_IsChannelRunning(uint8 instance, uint8 channel) { boolean isRunning = (boolean)FALSE; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { isRunning = ((pitBase[instance]->RTI_TCTRL & PIT_RTI_TCTRL_TEN_MASK) == PIT_RTI_TCTRL_TEN_MASK) ? (boolean)TRUE : (boolean)FALSE; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ isRunning = ((pitBase[instance]->TIMER[channel].TCTRL & PIT_TCTRL_TEN_MASK) == PIT_TCTRL_TEN_MASK) ? (boolean)TRUE : (boolean)FALSE; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ return isRunning; } /** * @brief Pit_Ip_SetCounterValue * @details Support set counter value PIT * This register is intended for Timer Load Value * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @param[in] value Value counter * * @return void * @pre The driver needs to be initialized. */ static inline void Pit_Ip_SetCounterValue(uint8 instance, uint8 channel, uint32 value) { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_LDVAL = value; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].LDVAL = value; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } /** * @brief Pit_Ip_GetCounterValue * @details Support get counter value PIT * This register is intended for Current Timer Value * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * * @return counterValue * @pre The driver needs to be initialized. */ static inline uint32 Pit_Ip_GetCounterValue(uint8 instance, uint8 channel) { uint32 counterValue = 0U; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { counterValue = pitBase[instance]->RTI_CVAL; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ counterValue = pitBase[instance]->TIMER[channel].CVAL; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ return counterValue; } /** * @brief Pit_Ip_EnableInterrupt * @details Support PIT clear interrupt flags * This register is intended for Timer Interrupt Flag * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @param[in] enable Enable interrupt * @return void * @pre The driver needs to be initialized. */ static inline void Pit_Ip_EnableInterrupt(uint8 instance, uint8 channel, boolean enable) { SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_02(); { if ((boolean)TRUE == enable) { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_TCTRL |= PIT_RTI_TCTRL_TIE_MASK; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].TCTRL |= PIT_TCTRL_TIE_MASK; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } else { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_TCTRL &= ~PIT_RTI_TCTRL_TIE_MASK; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].TCTRL &= ~PIT_TCTRL_TIE_MASK; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } } SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_02(); } /** * @brief Pit_Ip_ClearInterruptFlag * @details Support PIT clear interrupt flags * This register is intended for Timer Interrupt Flag * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return void * @pre The driver needs to be initialized. */ static inline void Pit_Ip_ClearInterruptFlag(uint8 instance, uint8 channel) { SchM_Enter_Gpt_GPT_EXCLUSIVE_AREA_03(); { #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { pitBase[instance]->RTI_TFLG |= PIT_RTI_TFLG_TIF_MASK; } else { #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ pitBase[instance]->TIMER[channel].TFLG |= PIT_TFLG_TIF_MASK; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ } SchM_Exit_Gpt_GPT_EXCLUSIVE_AREA_03(); } #if ((defined PIT_0_ISR_USED)||(defined PIT_1_ISR_USED)||(defined PIT_2_ISR_USED)) /** * @brief Pit_Ip_GetInterruptBit * @details Support interrupt bit * This register is intended for Timer Interrupt Enable. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return returnFlag * @pre The driver needs to be initialized. */ static inline uint32 Pit_Ip_GetInterruptBit(uint8 instance, uint8 channel) { uint32 returnFlag = 0U; #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if (RTI == channel) { returnFlag = ((pitBase[instance]->RTI_TCTRL & PIT_RTI_TCTRL_TIE_MASK) >> PIT_RTI_TCTRL_TIE_SHIFT); } else #endif { returnFlag = ((pitBase[instance]->TIMER[channel].TCTRL & PIT_TCTRL_TIE_MASK) >> PIT_TCTRL_TIE_SHIFT); } return returnFlag; } #endif /** * @brief Pit_Ip_GetUpperLifetimerValue * @details Support Get Upper life time value * This register is intended for applications that chain timer. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return upperValue * @pre The driver needs to be initialized. */ static inline uint32 Pit_Ip_GetUpperLifetimerValue(uint8 instance) { uint32 upperValue = 0U; upperValue = pitBase[instance]->LTMR64H; return upperValue; } /** * @brief Pit_Ip_GetLowerLifetimerValue * @details Support Get lower life time value * This register is intended for applications that chain timer. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return lowerValue * @pre The driver needs to be initialized. */ static inline uint32 Pit_Ip_GetLowerLifetimerValue(uint8 instance) { uint32 lowerValue = 0U; lowerValue = pitBase[instance]->LTMR64L; return lowerValue; } #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) static void Pit_Ip_StartTimeout(uint32 *startTimeOut, uint32 *elapsedTimeOut, uint32 *timeoutTicksOut, uint32 timeoutUs) { *startTimeOut = OsIf_GetCounter(PIT_IP_TIMEOUT_TYPE); *elapsedTimeOut = 0U; *timeoutTicksOut = OsIf_MicrosToTicks(timeoutUs, PIT_IP_TIMEOUT_TYPE); } static boolean Pit_Ip_TimeoutExpired(uint32 *startTimeInOut, uint32 *elapsedTimeInOut, uint32 timeoutTicks) { *elapsedTimeInOut += OsIf_GetElapsed(startTimeInOut, PIT_IP_TIMEOUT_TYPE); return ((*elapsedTimeInOut >= timeoutTicks)? TRUE : FALSE); } #if (PIT_IP_REPORT_ERROR_STATUS == STD_ON) void Pit_Ip_ErrorReport(void) { /* pit_rti has timeout */ DevAssert(TRUE); } #endif #endif #if ((defined PIT_0_ISR_USED)||(defined PIT_1_ISR_USED)||(defined PIT_2_ISR_USED)) /** * @brief Driver routine to process all the interrupts of PIT. * @details Support function used by interrupt service routines to implement PIT specific operations * and call the upper layer handler to implement non-hardware specific operations. * * @param[in] instance PIT hw instance number * @param[in] channel PIT hw channel number * @return void * @pre Enable interrupt service routines * @implements Pit_Ip_ProcessCommonInterrupt_Activity */ static void Pit_Ip_ProcessCommonInterrupt(uint8 instance, uint8 channel) { uint32 temp1; uint32 temp2; /*Checks for spurious interrupts*/ temp1 = Pit_Ip_GetInterruptFlags(instance, channel); temp2 = Pit_Ip_GetInterruptBit(instance, channel); /* Clear interrupt flag */ Pit_Ip_ClearInterruptFlag(instance, channel); if ((1U == temp1) && (1U == temp2)) { #if (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) Pit_Ip_bIsChangedTimeout = (boolean)FALSE; #endif /* Call upper layer handler */ if(((boolean)TRUE == Pit_Ip_u32ChState[instance][channel].chInit) && \ (NULL_PTR != Pit_Ip_u32ChState[instance][channel].callback)) { Pit_Ip_u32ChState[instance][channel].callback(Pit_Ip_u32ChState[instance][channel].callbackParam); } } } #endif /*================================================================================================== * GLOBAL FUNCTIONS ==================================================================================================*/ /** * @brief Function Name : Pit_Ip_Init * @details Driver initialization function. This function is called for each PIT hw Instance and * - enables the functional clock for PIT Instance or for RTI_PIT * - Sets PIT operation in Debug mode * * @param[in] instance PIT hw instance number * @param[in] configPtr Pointer to a selected configuration structure * @return void * @pre The data structure including the configuration set required for initializing the driver * @implements Pit_Ip_Init_Activity */ void Pit_Ip_Init(uint8 instance, const Pit_Ip_InstanceConfigType *config) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(NULL_PTR != config); #endif /* Enable register access from user mode, if enabled from configuration file */ Call_Pit_Ip_SetUserAccessAllowed((uint32)pitBase[instance]); /* Enables functional clock for standard timer */ if (config->enableStandardTimers) { Pit_Ip_EnableModule(instance, 0U); } #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) /* Enables functional clock for RTI timer */ if (config->enableRTITimer) { Pit_Ip_EnableModule(instance, 1U); } #endif /* FEATURE_PIT_HAS_RTI_CHANNEL */ /* Sets PIT operation in Debug mode*/ Pit_Ip_SetDebugMode(instance, config->stopRunInDebug); } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_InitChannel * @details Initializes the PIT channels. This function should be called for each PIT hw channel and: * - stops channel * - disable interrupts * - clears pending interrupts * - initializes the state sructure for common process interrupt * * @param[in] instance PIT hw instance number * @param[in] chnlConfig Pointer to a selected configuration structure. * @return void * @pre The data structure including the configuration set required for initializing the driver. * @implements Pit_Ip_InitChannel_Activity */ void Pit_Ip_InitChannel(uint8 instance, const Pit_Ip_ChannelConfigType *chnlConfig) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(NULL_PTR != chnlConfig); DevAssert(PIT_CHANNEL_COUNT > chnlConfig->hwChannel); #endif /*Stop channel to configure channel*/ Pit_Ip_EnableTimer(instance, chnlConfig->hwChannel, FALSE); /*Disable Interrupts */ Pit_Ip_EnableInterrupt(instance, chnlConfig->hwChannel, FALSE); /*Clear pending interrupts */ Pit_Ip_ClearInterruptFlag(instance, chnlConfig->hwChannel); #if ((defined PIT_0_ISR_USED)||(defined PIT_1_ISR_USED)||(defined PIT_2_ISR_USED)) Pit_Ip_u32ChState[instance][chnlConfig->hwChannel].chInit = TRUE; Pit_Ip_u32ChState[instance][chnlConfig->hwChannel].callback = chnlConfig->callback; Pit_Ip_u32ChState[instance][chnlConfig->hwChannel].callbackParam = chnlConfig->callbackParam; #endif #if ((defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) && (PIT_IP_REPORT_ERROR_STATUS == STD_ON)) Pit_Ip_u32ChState[instance][chnlConfig->hwChannel].errorReportCallBack = chnlConfig->errorReportCallBack; #endif } /*================================================================================================*/ /** * @brief Pit_Ip_DeInit * @details De-Initializes the PIT instances. This functions is called for each PIT Instance and * - resets all channels to default * * @param[in] instance Pit hw instance * @return void * @pre The data structure including the configuration set required for initializing the GPT driver. * @implements Pit_Ip_Deinit_Activity * */ void Pit_Ip_Deinit(uint8 instance) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); #endif uint8 channelNum = 0U; boolean rtiChannelExists = FALSE; switch (instance) { #ifdef PIT_0_EXISTS case 0: channelNum = PIT_0_CHANNELS_NUMBER; #ifdef PIT_RTI_CHANNEL_EXISTS rtiChannelExists = TRUE; #endif break; #endif #ifdef PIT_1_EXISTS case 1: channelNum = PIT_1_CHANNELS_NUMBER; break; #endif #ifdef PIT_2_EXISTS case 2: channelNum = PIT_2_CHANNELS_NUMBER; break; #endif default: /*This switch branch is empty because it shall not be executed for normal behaviour*/ break; } /* Set control, load, status registers to default value */ Pit_Ip_Reset(instance, channelNum, rtiChannelExists); } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_StartChannel * @details This function is called for starting the Pit timer channel. * - sets the timeout value into the PIT timer channel register * - enables the PIT channel * * @param[in] instance Pit hw instance * @param[in] channel Pit hw channel * @param[in] countValue channel timeout value * @return void * @pre The driver needs to be initialized. This function is called for starting the Pit timer channel. * @implements Pit_Ip_StartChannel_Activity */ void Pit_Ip_StartChannel(uint8 instance, uint8 channel, uint32 countValue) { boolean isRunning = (boolean)FALSE; #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); DevAssert(PIT_MAX_VALUE > countValue); #endif #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) Pit_Ip_StatusType status = PIT_IP_ERROR; uint32 startTime, elapsedTime, timeoutTicks; Pit_Ip_StartTimeout(&startTime, &elapsedTime, &timeoutTicks, PIT_IP_TIMEOUT_COUNTER); #endif isRunning = Pit_Ip_IsChannelRunning(instance, channel); if((boolean)FALSE == isRunning) { Pit_Ip_SetCounterValue(instance, channel, (countValue - 1U)); #if (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) Pit_Ip_bIsChangedTimeout = (boolean)FALSE; #endif #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) do { if ((countValue - 1U) == Pit_Ip_GetCounterValue(instance, channel)) { status = PIT_IP_SUCCESS; break; } } while (!Pit_Ip_TimeoutExpired(&startTime, &elapsedTime, timeoutTicks)); if(PIT_IP_SUCCESS != status) { #if (PIT_IP_REPORT_ERROR_STATUS == STD_ON) /* if error report is enabled */ Pit_Ip_u32ChState[instance][channel].errorReportCallBack(); #endif } else { #endif Pit_Ip_EnableTimer(instance, channel, TRUE); #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) } #endif } } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_StopChannel * @details This function is called for stopping the Pit counter. This function disables the PIT channel and: * - stops PIT counter * - clears interrupt flag * * @param[in] instance Pit hw instance * @param[in] channel Pit hw channel * @return void * @pre The driver needs to be initialized. Pit_Ip_StartChannel must be call before. * @implements Pit_Ip_StopChannel_Activity */ void Pit_Ip_StopChannel(uint8 instance, uint8 channel) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); #endif Pit_Ip_EnableTimer(instance, channel, FALSE); Pit_Ip_ClearInterruptFlag(instance, channel); } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_GetCurrentTimer * @details Gets counter value from CVAL Register. * The period range depends on the frequency of the PIT source clock * * * @param[in] instance Pit hw instance * @param[in] channel Pit hw channel * * @return counterValue counter value * @pre The driver needs to be initialized. * @implements Pit_Ip_GetCurrentTimer_Activity */ uint64 Pit_Ip_GetCurrentTimer(uint8 instance, uint8 channel) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); #endif uint64 counterValue = 0U; counterValue = Pit_Ip_GetCounterValue(instance, channel); return counterValue; } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_EnableChannelInterrupt * @details This function enables the IRQ corresponding to the Pit timer channel * * * @param[in] instance Pit hw instance * @param[in] channel Pit hw channel * @return void * @pre The driver needs to be initialized. * @implements Pit_Ip_EnableChannelInterrupt_Activity */ void Pit_Ip_EnableChannelInterrupt(uint8 instance, uint8 channel) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); #endif Pit_Ip_ClearInterruptFlag(instance, channel); Pit_Ip_EnableInterrupt(instance, channel, TRUE); } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_DisableChannelInterrupt * @details This function disables the IRQ corresponding to the Pit timer channel * * * @param[in] instance Pit hw instance * @param[in] channel Pit hw channel * @return void * @pre The driver needs to be initialized. * @implements Pit_Ip_DisableChannelInterrupt_Activity */ void Pit_Ip_DisableChannelInterrupt(uint8 instance, uint8 channel) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); #endif Pit_Ip_EnableInterrupt(instance, channel, FALSE); Pit_Ip_ClearInterruptFlag(instance, channel); } /*================================================================================================*/ #if (PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON) /** * @brief The function changes Pit Timer Load Value Register value. * @details This function: * - sets the next timeout value to PIT_RTI_LDVAL. * * @param[in] u8HwChannel Pit hw channel ID * @param[in] u32Value channel timeout value * @return void * @pre The driver needs to be initialized. PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON * @implements Pit_Ip_ChangeNextTimeoutValue_Activity */ void Pit_Ip_ChangeNextTimeoutValue(uint8 instance, uint8 channel, uint32 value) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); DevAssert(PIT_MAX_VALUE > value); #endif if((boolean)FALSE == Pit_Ip_bIsChangedTimeout) { Pit_Ip_u32OldTargetValue = Pit_Ip_GetLoadValue(instance, channel) + 1U; Pit_Ip_bIsChangedTimeout = (boolean)TRUE; } Pit_Ip_SetCounterValue(instance, channel, (value - 1U)); } #endif /* PIT_IP_CHANGE_NEXT_TIMEOUT_VALUE == STD_ON */ /*================================================================================================*/ #if (PIT_IP_CHAIN_MODE == STD_ON) /** * @brief The function Pit_Ip_EnableChainMode. * @details This function: * - Chains the timers. * @param[in] instance Pit hw channel ID * @param[in] channel channel timeout value * @return returnValue * @pre The driver needs to be initialized. PIT_IP_CHAIN_MODE == STD_ON * @implements Pit_Ip_ChainMode_Activity */ Pit_Ip_StatusType Pit_Ip_ChainMode(uint8 instance, uint8 channel, boolean enable) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); DevAssert(PIT_CHANNEL_COUNT > channel); #endif Pit_Ip_StatusType returnValue = PIT_IP_ERROR; /* Can not enable chain mode for PIT_RTI and CH_0 */ #if (defined (PIT_IP_RTI_USED) && (PIT_IP_RTI_USED == STD_ON)) if(((uint8) 0x00 < channel) && (RTI != channel)) #else if((uint8) 0x00 < channel) #endif { /* Enable Chain Mode*/ Pit_Ip_SetChainMode(instance, channel, enable); returnValue = PIT_IP_SUCCESS; } return returnValue; } #endif /*(PIT_IP_CHAIN_MODE == STD_ON)*/ /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_SetLifetimeTimerCount * @details Build the 64-bit lifetimer. * The lifetime timer is a 64-bit timer which chains timer channel 0 and timer channel 1 together * with the start value of both channels is set to the maximum value(0xFFFFFFFF). * The period of lifetime timer is equal to the "period of * timer 0 * period of timer 1". * * @param[in] instance Pit hw instance * @return void * @pre The driver needs to be initialized. * @implements Pit_Ip_SetLifetimeTimerCount_Activity */ void Pit_Ip_SetLifetimeTimerCount(uint8 instance) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); #endif /* Setup timer channel 1 for maximum counting period */ Pit_Ip_SetCounterValue(instance, 1U, PIT_MAX_VALUE); /* Disable timer channel 1 interrupt */ Pit_Ip_EnableInterrupt(instance, 1U, FALSE); /* Chain timer channel 1 to timer channel 0 */ Pit_Ip_SetChainMode(instance, 1U, TRUE); /* Start timer channel 1 */ Pit_Ip_EnableTimer(instance, 1U, TRUE); /* Setup timer channel 0 for maximum counting period */ Pit_Ip_SetCounterValue(instance, 0U, PIT_MAX_VALUE); /* Start timer channel 0 */ Pit_Ip_EnableTimer(instance, 0U, TRUE); } /*================================================================================================*/ /** * @brief Function Name : Pit_Ip_GetLifetimeTimer * @details Read current lifefime counter value. * The Lifetime timer is 64-bit timer which chains timer 0 and timer 1 together. * The period of lifetime timer equals to "period of timer 0 * period of timer 1". * This feature returns an absolute time stamp in count. The time stamp * value does not exceed the timer period. The timer is down-counting. * * @param[in] instance Pit hw instance * * @return lifeTimeValue * @pre The driver needs to be initialized. * @implements Pit_Ip_GetLifetimeTimer_Activity */ uint64 Pit_Ip_GetLifetimeTimer(uint8 instance) { #if PIT_IP_DEV_ERROR_DETECT == STD_ON DevAssert(PIT_INSTANCE_COUNT > instance); #endif uint64 lifeTimeValue = 0U; uint32 valueH = 0U; uint32 valueL = 0U; /* TODO: ERRATA versioning*/ #ifdef ERRATA_E50130 if (valueL == Pit_Ip_GetLoadValue(instance, channel)) { /* The errata's workaround: Read LTMR64H and LTMR64L again after one PIT cycle clock delay from the first reading. The "while" loop ensures that at least one PIT clock cycle had occurred. */ while(valueL == Pit_Ip_GetCounterValue(instance, channel)) { /* Do nothing */ #endif valueH = Pit_Ip_GetUpperLifetimerValue(instance); valueL = Pit_Ip_GetLowerLifetimerValue(instance); #ifdef ERRATA_E50130 } } #endif lifeTimeValue = (((uint64)valueH << 32U) + (uint64)(valueL)); return lifeTimeValue; } /*================================================================================================*/ #if (PIT_IP_MODULE_SINGLE_INTERRUPT == STD_ON) #ifdef PIT_0_ISR_USED /** * @brief Interrupt handler for PIT_0 channels. * @details Interrupt Service Routine corresponding to PIT_0 hw module. * @param[in] none * @return void * @isr * @pre The driver needs to be initialized */ ISR(PIT_0_ISR) { uint8 instance = 0U; uint8 channel; uint32 temp = 0; for (channel = 0U; channel < PIT_0_CHANNELS_NUMBER; channel++) { temp = Pit_Ip_GetInterruptFlags(instance, channel); if (1U == temp) { Pit_Ip_ProcessCommonInterrupt(instance, channel); } } } #endif /*================================================================================================*/ #ifdef PIT_1_ISR_USED /** * @brief Interrupt handler for PIT_1 channels. * @details Interrupt Service Routine corresponding to PIT_1 hw module. * @param[in] none * @return void * @isr * @pre The driver needs to be initialized. */ ISR(PIT_1_ISR) { uint8 instance = 1U; uint8 channel; uint32 temp = 0; for (channel = 0U; channel < PIT_1_CHANNELS_NUMBER; channel++) { temp = Pit_Ip_GetInterruptFlags(instance, channel); if (1U == temp) { Pit_Ip_ProcessCommonInterrupt(instance, channel); } } } #endif /*================================================================================================*/ #ifdef PIT_2_ISR_USED /** * @brief Interrupt handler for PIT_2 channels. * @details Interrupt Service Routine corresponding to PIT_2 hw module. * @param[in] none * @return void * @isr * @pre The driver needs to be initialized */ ISR(PIT_2_ISR) { uint8 instance = 2U; uint8 channel; uint32 temp = 0; for (channel = 0U; channel < PIT_2_CHANNELS_NUMBER; channel++) { temp = Pit_Ip_GetInterruptFlags(instance, channel); if (1U == temp) { Pit_Ip_ProcessCommonInterrupt(instance, channel); } } } #endif /*================================================================================================*/ #endif /*PIT_IP_MODULE_SINGLE_INTERRUPT == STD_ON*/ #define GPT_STOP_SEC_CODE #include "Gpt_MemMap.h" #endif /* PIT_IP_USED == STD_ON */ #ifdef __cplusplus } #endif /* PIT_IP_C */ /** @} */