ADM/GW/RTD/src/Pit_Ip.c
2024-08-08 10:00:15 +09:00

1300 lines
45 KiB
C

/*==================================================================================================
* 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 */
/** @} */