blob: ef422ec602ddc290ea0389e3e41bc9dbb358d9a1 [file] [log] [blame]
/*
* Copyright 2018-2019 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "generic_list.h"
#include "timer_manager.h"
#include "timer.h"
#if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
#include "time_stamp.h"
#endif
/*
* The OSA_USED macro can only be defined when the OSA component is used.
* If the source code of the OSA component does not exist, the OSA_USED cannot be defined.
* OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED
* also cannot be defined.
* The source code path of the OSA component is <MCUXpresso_SDK>/components/osa.
*
*/
#if defined(OSA_USED)
#include "fsl_os_abstraction.h"
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
#include "common_task.h"
#endif
#endif
/*****************************************************************************
******************************************************************************
* Private macros
******************************************************************************
*****************************************************************************/
#define mTmrDummyEvent_c (1 << 16)
/**@brief Timer status. */
typedef enum _timer_state
{
kTimerStateFree_c = 0x00, /**< The timer free status. */
kTimerStateActive_c = 0x20, /**< The timer active status. */
kTimerStateReady_c = 0x40, /**< The timer ready status. */
kTimerStateInactive_c = 0x80, /**< The timer inactive status. */
kTimerStateMask_c = 0xE0, /**< The timer status mask all. */
kTimerModeMask_c = 0x1F, /**< The timer mode mask all. */
} timer_state_t;
/*****************************************************************************
******************************************************************************
* Private type definitions
******************************************************************************
*****************************************************************************/
/*! @brief Timer handle structure for timer manager. */
#if (defined(GENERIC_LIST_LIGHT) && (GENERIC_LIST_LIGHT > 0U))
typedef struct _timer_handle_struct_t
{
list_element_t link; /*!< LIST_ element of the link */
uint64_t timeoutInUs; /*!< Time out of the timer, should be microseconds */
uint64_t remainingUs; /*!< Remaining of the timer, should be microseconds */
timer_callback_t pfCallBack; /*!< Callback function of the timer */
void *param; /*!< Parameter of callback function of the timer */
volatile uint8_t tmrStatus; /*!< Timer status and mode*/
} timer_handle_struct_t;
#else
typedef struct _timer_handle_struct_t
{
list_element_t link; /*!< LIST_ element of the link */
volatile uint8_t tmrStatus; /*!< Timer status and mode*/
uint64_t timeoutInUs; /*!< Time out of the timer, should be microseconds */
uint64_t remainingUs; /*!< Remaining of the timer, should be microseconds */
timer_callback_t pfCallBack; /*!< Callback function of the timer */
void *param; /*!< Parameter of callback function of the timer */
} timer_handle_struct_t;
#endif
/*! @brief State structure for timer manager. */
typedef struct _timermanager_state
{
uint32_t mUsInTimerInterval; /*!< Timer intervl in microseconds */
uint32_t previousTimeInUs; /*!< Previous timer count in microseconds */
list_label_t timerHead; /*!< Timer list head */
TIMER_HANDLE_DEFINE(halTimerHandle); /*!< Timer handle buffer */
#if defined(OSA_USED)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
common_task_message_t mTimerCommontaskMsg; /*!< Timer common_task message */
#else
OSA_EVENT_HANDLE_DEFINE(halTimerTaskEventHandle); /*!< Timer task event handle buffer */
OSA_TASK_HANDLE_DEFINE(timerTaskHandle); /*!< Timer task id */
#endif
#endif
volatile uint8_t numberOfActiveTimers; /*!< Number of active Timers*/
volatile uint8_t numberOfLowPowerActiveTimers; /*!< Number of low power active Timers */
volatile uint8_t timerHardwareIsRunning; /*!< Hardware timer is runnig */
} timermanager_state_t;
/*****************************************************************************
******************************************************************************
* Public memory declarations
******************************************************************************
*****************************************************************************/
#if defined(OSA_USED)
extern const uint8_t gUseRtos_c;
#endif
/*****************************************************************************
*****************************************************************************
* Private prototypes
*****************************************************************************
*****************************************************************************/
/*! -------------------------------------------------------------------------
* \brief Function called by driver ISR on channel match in interrupt context.
*---------------------------------------------------------------------------*/
static void HAL_TIMER_Callback(void *param);
/*! -------------------------------------------------------------------------
* \brief Timer thread.
* Called by the kernel when the timer ISR posts a timer event.
* \param[in] param - User parameter to timer thread; not used.
*---------------------------------------------------------------------------*/
static void TimerManagerTask(void *param);
static void TimerEnable(timer_handle_t timerHandle);
/*****************************************************************************
*****************************************************************************
* Private memory definitions
*****************************************************************************
*****************************************************************************/
static timermanager_state_t s_timermanager = {0};
/*****************************************************************************
******************************************************************************
* Private API macro define
******************************************************************************
*****************************************************************************/
#define IncrementActiveTimerNumber(type) \
((((type) & (uint8_t)kTimerModeLowPowerTimer) != 0U) ? (++s_timermanager.numberOfLowPowerActiveTimers) : \
(++s_timermanager.numberOfActiveTimers))
#define DecrementActiveTimerNumber(type) \
((((type) & (uint8_t)kTimerModeLowPowerTimer) != 0U) ? (--s_timermanager.numberOfLowPowerActiveTimers) : \
(--s_timermanager.numberOfActiveTimers))
/*
* \brief Detect if the timer is a low-power timer
*/
#define IsLowPowerTimer(type) ((type) & (uint8_t)kTimerModeLowPowerTimer)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
#else
/*
* \brief Defines the timer thread's stack
*/
OSA_TASK_DEFINE(TimerManagerTask, TM_TASK_PRIORITY, 1, TM_TASK_STACK_SIZE, false);
#endif
/*****************************************************************************
******************************************************************************
* Private functions
******************************************************************************
*****************************************************************************/
/*!-------------------------------------------------------------------------
* \brief Returns the timer status
* \param[in] timerHandle - the handle of timer
* \return see definition of uint8_t
*---------------------------------------------------------------------------*/
static uint8_t TimerGetTimerStatus(timer_handle_t timerHandle)
{
timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
return timer->tmrStatus & (uint8_t)kTimerStateMask_c;
}
/*! -------------------------------------------------------------------------
* \brief Set the timer status
* \param[in] timerHandle - the handle of timer
* \param[in] status - the status of the timer
*---------------------------------------------------------------------------*/
static void TimerSetTimerStatus(timer_handle_t timerHandle, uint8_t status)
{
timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
timer->tmrStatus &= (~(uint8_t)kTimerStateMask_c);
timer->tmrStatus |= status;
}
/*! -------------------------------------------------------------------------
* \brief Returns the timer type
* \param[in] timerHandle - the handle of timer
* \return see definition of uint8_t
*---------------------------------------------------------------------------*/
static uint8_t TimerGetTimerType(timer_handle_t timerHandle)
{
timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
return timer->tmrStatus & (uint8_t)kTimerModeMask_c;
}
/*! -------------------------------------------------------------------------
* \brief Set the timer type
* \param[in] timerHandle - the handle of timer
* \param[in] timerType - timer type
*---------------------------------------------------------------------------*/
static void TimerSetTimerType(timer_handle_t timerHandle, uint8_t timerType)
{
timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
timer->tmrStatus &= (~(uint8_t)kTimerModeMask_c);
timer->tmrStatus |= timerType;
}
/*! -------------------------------------------------------------------------
* \brief Set the timer free
* \param[in] timerHandle - the handle of timer
* \param[in] type - timer type
*---------------------------------------------------------------------------*/
static void TimerMarkTimerFree(timer_handle_t timerHandle)
{
timer_handle_struct_t *timer = (timer_handle_struct_t *)timerHandle;
timer->tmrStatus = 0;
}
/*! -------------------------------------------------------------------------
* \brief Notify Timer task to run.
* \return
*---------------------------------------------------------------------------*/
static void NotifyTimersTask(void)
{
#if defined(OSA_USED)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
s_timermanager.mTimerCommontaskMsg.callback = TimerManagerTask;
COMMON_TASK_post_message(&s_timermanager.mTimerCommontaskMsg);
#else
(void)OSA_EventSet((osa_event_handle_t)s_timermanager.halTimerTaskEventHandle, mTmrDummyEvent_c);
#endif
#else
TimerManagerTask(NULL);
#endif
}
/*! -------------------------------------------------------------------------
* \brief Update Remaining Us for all Active timers
* \return
*---------------------------------------------------------------------------*/
static void TimersUpdate(bool updateRemainingUs, bool updateOnlyPowerTimer, uint32_t remainingUs)
{
list_element_handle_t list_element;
list_handle_t timerHandle = &s_timermanager.timerHead;
assert(timerHandle);
if ((s_timermanager.numberOfLowPowerActiveTimers != 0U) || (s_timermanager.numberOfActiveTimers != 0U))
{
list_element = LIST_GetHead(timerHandle);
while (list_element != NULL)
{
timer_handle_struct_t *th = (timer_handle_struct_t *)(void *)list_element;
if (updateRemainingUs)
{
if ((timer_state_t)TimerGetTimerStatus(th) == kTimerStateActive_c)
{
if ((updateOnlyPowerTimer && (0U != IsLowPowerTimer(TimerGetTimerType(th)))) ||
(!updateOnlyPowerTimer))
{
if (th->remainingUs > remainingUs)
{
th->remainingUs = th->remainingUs - remainingUs;
}
else
{
th->remainingUs = 0;
}
}
}
}
list_element = LIST_GetNext(list_element);
}
}
}
/*! -------------------------------------------------------------------------
* \brief Update Remaining Us for all Active timers and sync timer task
* \return
*---------------------------------------------------------------------------*/
static void TimersUpdateSyncTask(uint32_t remainingUs)
{
TimersUpdate(true, false, remainingUs);
s_timermanager.previousTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
NotifyTimersTask();
}
/*! -------------------------------------------------------------------------
* \brief Function called by driver ISR on channel match in interrupt context.
*---------------------------------------------------------------------------*/
static void HAL_TIMER_Callback(void *param)
{
TimersUpdateSyncTask(s_timermanager.mUsInTimerInterval);
}
/*! -------------------------------------------------------------------------
* \brief TimerManager task.
* Called by the kernel when the timer ISR posts a timer event.
* \param[in] param
*---------------------------------------------------------------------------*/
static void TimerManagerTask(void *param)
{
uint8_t timerType;
list_element_handle_t list_element;
timer_state_t state;
static uint32_t mpevUsInTimerInterval = 0;
uint8_t activeLPTimerNum, activeTimerNum;
list_handle_t timerHandle = &s_timermanager.timerHead;
#if defined(OSA_USED)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
{
#else
osa_event_flags_t ev = 0;
do
{
if (KOSA_StatusSuccess == OSA_EventWait((osa_event_handle_t)s_timermanager.halTimerTaskEventHandle,
osaEventFlagsAll_c, false, osaWaitForever_c, &ev))
{
#endif
#endif
uint32_t regPrimask = DisableGlobalIRQ();
s_timermanager.mUsInTimerInterval = HAL_TimerGetMaxTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle);
list_element = LIST_GetHead(timerHandle);
while (NULL != list_element)
{
timer_handle_struct_t *th = (timer_handle_struct_t *)(void *)list_element;
timerType = TimerGetTimerType(th);
state = (timer_state_t)TimerGetTimerStatus(th);
if (kTimerStateReady_c == state)
{
TimerSetTimerStatus(th, (uint8_t)kTimerStateActive_c);
if (s_timermanager.mUsInTimerInterval > th->timeoutInUs)
{
s_timermanager.mUsInTimerInterval = (uint32_t)th->timeoutInUs;
}
}
if (kTimerStateActive_c == state)
{
/* This timer is active. Decrement it's countdown.. */
if (0U >= th->remainingUs)
{
/* If this is an interval timer, restart it. Otherwise, mark it as inactive. */
if (0U != (timerType & (uint32_t)(kTimerModeSingleShot)))
{
th->remainingUs = 0;
(void)TM_Stop(th);
state = (timer_state_t)TimerGetTimerStatus(th);
}
else
{
th->remainingUs = th->timeoutInUs;
}
/* This timer has expired. */
/*Call callback if it is not NULL*/
EnableGlobalIRQ(regPrimask);
if (NULL != th->pfCallBack)
{
th->pfCallBack(th->param);
}
regPrimask = DisableGlobalIRQ();
}
if ((kTimerStateActive_c == state) && (s_timermanager.mUsInTimerInterval > th->remainingUs))
{
s_timermanager.mUsInTimerInterval = (uint32_t)th->remainingUs;
}
}
else
{
/* Ignore any timer that is not active. */
}
list_element = LIST_GetNext(list_element);
}
activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
activeTimerNum = s_timermanager.numberOfActiveTimers;
if ((0U != activeLPTimerNum) || (0U != activeTimerNum))
{
if ((s_timermanager.mUsInTimerInterval != mpevUsInTimerInterval) ||
(0U == s_timermanager.timerHardwareIsRunning))
{
HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
(void)HAL_TimerUpdateTimeout((hal_timer_handle_t)s_timermanager.halTimerHandle,
s_timermanager.mUsInTimerInterval);
HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
mpevUsInTimerInterval = s_timermanager.mUsInTimerInterval;
}
s_timermanager.timerHardwareIsRunning = (uint8_t) true;
}
else
{
if (0U != s_timermanager.timerHardwareIsRunning)
{
HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
s_timermanager.timerHardwareIsRunning = (uint8_t) false;
s_timermanager.mUsInTimerInterval = 0;
}
}
EnableGlobalIRQ(regPrimask);
#if defined(OSA_USED)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
}
#else
}
} while (gUseRtos_c);
#endif
#endif
}
/*! -------------------------------------------------------------------------
* \brief Enable the specified timer
* \param[in] timerHandle - the handle of the timer
*---------------------------------------------------------------------------*/
static void TimerEnable(timer_handle_t timerHandle)
{
assert(timerHandle);
uint32_t regPrimask = DisableGlobalIRQ();
if ((uint8_t)kTimerStateInactive_c == TimerGetTimerStatus(timerHandle))
{
IncrementActiveTimerNumber(TimerGetTimerType(timerHandle));
TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateReady_c);
TimersUpdateSyncTask(HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle));
}
EnableGlobalIRQ(regPrimask);
}
/*****************************************************************************
******************************************************************************
* Public functions
******************************************************************************
*****************************************************************************/
/*!
* @brief Initializes timer manager module with the user configuration structure.
*
*
* @param timerConfig Pointer to user-defined timer configuration structure.
* @retval kStatus_TimerSuccess Timer manager initialization succeed.
* @retval kStatus_TimerError An error occurred.
*/
timer_status_t TM_Init(timer_config_t *timerConfig)
{
static uint32_t initialized = 0;
hal_timer_config_t halTimerConfig;
hal_timer_handle_t halTimerHandle = &s_timermanager.halTimerHandle[0];
hal_timer_status_t status;
assert(timerConfig);
/* Check if TMR is already initialized */
if (0U == initialized)
{
LIST_Init((&s_timermanager.timerHead), 0);
halTimerConfig.timeout = 1000;
halTimerConfig.srcClock_Hz = timerConfig->srcClock_Hz;
halTimerConfig.instance = timerConfig->instance;
status = HAL_TimerInit(halTimerHandle, &halTimerConfig);
assert(kStatus_HAL_TimerSuccess == status);
(void)status;
HAL_TimerInstallCallback(halTimerHandle, HAL_TIMER_Callback, NULL);
s_timermanager.mUsInTimerInterval = halTimerConfig.timeout;
#if defined(OSA_USED)
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
COMMON_TASK_init();
#else
status = OSA_EventCreate((osa_event_handle_t)s_timermanager.halTimerTaskEventHandle, true);
assert(KOSA_StatusSuccess == (osa_status_t)status);
status = OSA_TaskCreate((osa_task_handle_t)s_timermanager.timerTaskHandle, OSA_TASK(TimerManagerTask), NULL);
assert(KOSA_StatusSuccess == (osa_status_t)status);
#endif
#endif
#if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
hal_timer_stamp_config_t halTimerStampConfig;
halTimerStampConfig.srcClock_Hz = CLOCK_GetFreq(kCLOCK_BusClk);
HAL_TimerStampInit(&halTimerStampConfig);
#endif
initialized = 1U;
}
return kStatus_TimerSuccess;
}
/*!
* @brief Deinitialize timer manager module.
*
*/
void TM_Deinit(void)
{
#if (defined(TM_COMMON_TASK_ENABLE) && (TM_COMMON_TASK_ENABLE > 0U))
#else
OSA_EventDestroy((osa_event_handle_t)s_timermanager.halTimerTaskEventHandle);
OSA_TaskDestroy((osa_task_handle_t)s_timermanager.timerTaskHandle);
#endif
HAL_TimerDeinit((hal_timer_handle_t)s_timermanager.halTimerHandle);
(void)memset(&s_timermanager, 0x0, sizeof(s_timermanager));
}
/*!
* @brief Power up timer manager module.
*
*/
void TM_ExitLowpower(void)
{
#if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
HAL_TimerExitLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
#endif
}
/*!
* @brief Power down timer manager module.
*
*/
void TM_EnterLowpower(void)
{
#if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
HAL_TimerEnterLowpower((hal_timer_handle_t)s_timermanager.halTimerHandle);
#endif
}
/*!
* @brief Get a time-stamp value
*
*/
uint64_t TM_GetTimestamp(void)
{
#if (defined(TM_ENABLE_TIME_STAMP) && (TM_ENABLE_TIME_STAMP > 0U))
return HAL_GeTimerStamp();
#else
return 0U;
#endif /* TM_ENABLE_TIME_STAMP */
}
/*!
* @brief Open a timer with user handle.
*
* @param timerHandle Pointer to point to a memory space of size #TIMER_HANDLE_SIZE allocated by the
* caller.
* @retval kStatus_TimerSuccess Timer open succeed.
* @retval kStatus_TimerError An error occurred.
*/
timer_status_t TM_Open(timer_handle_t timerHandle)
{
timer_handle_struct_t *timerState = timerHandle;
assert(sizeof(timer_handle_struct_t) == TIMER_HANDLE_SIZE);
assert(timerHandle);
TimerSetTimerStatus(timerState, (uint8_t)kTimerStateInactive_c);
(void)LIST_AddTail((void *)&s_timermanager.timerHead, (list_element_handle_t) & (timerState->link));
return kStatus_TimerSuccess;
}
/*!
* @brief Close a timer with user handle.
*
* @param timerHandle - the handle of the timer
*
* @retval kStatus_TimerSuccess Timer close succeed.
* @retval kStatus_TimerError An error occurred.
*/
timer_status_t TM_Close(timer_handle_t timerHandle)
{
timer_status_t status;
assert(timerHandle);
status = TM_Stop(timerHandle);
assert(kStatus_TimerSuccess == status);
(void)status;
TimerMarkTimerFree(timerHandle);
(void)LIST_RemoveElement(timerHandle);
return kStatus_TimerSuccess;
}
/*!
* @brief Check if all timers except the LP timers are OFF
*
*
* @retval return 1 there are no active non-low power timers, 0 otherwise.
*/
uint8_t TM_AreAllTimersOff(void)
{
return s_timermanager.numberOfActiveTimers == 0U ? 1U : 0U ;
}
/*!
* @brief Check if a specified timer is active
*
* @param timerHandle - the handle of the timer
*
* @retval return 1 if timer is active, return 0 if timer is not active.
*/
uint8_t TM_IsTimerActive(timer_handle_t timerHandle)
{
assert(timerHandle);
return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateActive_c);
}
/*!
* @brief Check if a specified timer is ready
*
* @param timerHandle - the handle of the timer
*
* @retval return 1 if timer is ready, return 0 if timer is not ready.
*/
uint8_t TM_IsTimerReady(timer_handle_t timerHandle)
{
assert(timerHandle);
return (uint8_t)(TimerGetTimerStatus(timerHandle) == (uint8_t)kTimerStateReady_c);
}
/*!
* @brief Install a specified timer callback
*
* @param timerHandle - the handle of the timer
* @param callback - callback function
* @param callbackParam - parameter to callback function
*
* @retval kStatus_TimerSuccess Timer install callback succeed.
*
*/
timer_status_t TM_InstallCallback(timer_handle_t timerHandle, timer_callback_t callback, void *callbackParam)
{
timer_handle_struct_t *th = timerHandle;
assert(timerHandle);
th->pfCallBack = callback;
th->param = callbackParam;
return kStatus_TimerSuccess;
}
/*!
* @brief Start a specified timer
*
* @param timerHandle - the handle of the timer
* @param timerType - the type of the timer
* @param timerTimout - time expressed in millisecond units
*
* @retval kStatus_TimerSuccess Timer start succeed.
* @retval kStatus_TimerError An error occurred.
*/
timer_status_t TM_Start(timer_handle_t timerHandle, uint8_t timerType, uint32_t timerTimeout)
{
timer_status_t status;
timer_handle_struct_t *th = timerHandle;
assert(timerHandle);
/* Stopping an already stopped timer is harmless. */
status = TM_Stop(timerHandle);
assert(status == kStatus_TimerSuccess);
TimerSetTimerType(timerHandle, timerType);
if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetMinuteTimer))
{
th->timeoutInUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
th->remainingUs = (uint64_t)1000U * 1000U * 60U * timerTimeout;
}
else if (0U != ((uint8_t)timerType & (uint8_t)kTimerModeSetSecondTimer))
{
th->timeoutInUs = (uint64_t)1000U * 1000U * timerTimeout;
th->remainingUs = (uint64_t)1000U * 1000U * timerTimeout;
}
else
{
th->timeoutInUs = (uint64_t)1000U * timerTimeout;
th->remainingUs = (uint64_t)1000U * timerTimeout;
}
/* Enable timer, the timer task will do the rest of the work. */
TimerEnable(timerHandle);
return status;
}
/*!
* @brief Stop a specified timer
*
* @param timerHandle - the handle of the timer
*
* @retval kStatus_TimerSuccess Timer stop succeed.
* @retval kStatus_TimerError An error occurred.
*/
timer_status_t TM_Stop(timer_handle_t timerHandle)
{
timer_status_t status = kStatus_TimerInvalidId;
timer_state_t state;
uint8_t activeLPTimerNum, activeTimerNum;
uint32_t regPrimask = DisableGlobalIRQ();
if (NULL != timerHandle)
{
state = (timer_state_t)TimerGetTimerStatus(timerHandle);
status = kStatus_TimerSuccess;
if ((state == kTimerStateActive_c) || (state == kTimerStateReady_c))
{
TimerSetTimerStatus(timerHandle, (uint8_t)kTimerStateInactive_c);
DecrementActiveTimerNumber(TimerGetTimerType(timerHandle));
/* if no sw active timers are enabled, */
/* call the TimerManagerTask() to countdown the ticks and stop the hw timer*/
activeLPTimerNum = s_timermanager.numberOfLowPowerActiveTimers;
activeTimerNum = s_timermanager.numberOfActiveTimers;
if ((0U == activeTimerNum) && (0U == activeLPTimerNum))
{
if (0U != s_timermanager.timerHardwareIsRunning)
{
HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
s_timermanager.timerHardwareIsRunning = 0U;
}
}
}
}
EnableGlobalIRQ(regPrimask);
return status;
}
/*!
* @brief Returns the remaining time until timeout
*
* @param timerHandle - the handle of the timer
*
* @retval remaining time in microseconds until first timer timeouts.
*/
uint32_t TM_GetRemainingTime(timer_handle_t timerHandle)
{
timer_handle_struct_t *timerState = timerHandle;
assert(timerHandle);
return ((uint32_t)(timerState->remainingUs) -
(uint32_t)(HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle) -
s_timermanager.previousTimeInUs));
}
/*!
* @brief Get the first expire time of timer
*
* @param timerHandle - the handle of the timer
*
* @retval return the first expire time us of all timer.
*/
uint32_t TM_GetFirstExpireTime(uint8_t timerType)
{
uint32_t min = 0xFFFFFFFFU;
uint32_t remainingTime;
list_element_handle_t list_element;
list_handle_t timerHandle = &s_timermanager.timerHead;
list_element = LIST_GetHead(timerHandle);
while (NULL != list_element)
{
timer_handle_struct_t *th = (timer_handle_struct_t *)(void *)list_element;
if ((bool)TM_IsTimerActive(th) && ((timerType & TimerGetTimerType(timerHandle)) > 0U))
{
remainingTime = TM_GetRemainingTime(th);
if (remainingTime < min)
{
min = remainingTime;
}
}
list_element = LIST_GetNext(list_element);
}
return min;
}
/*!
* @brief Returns the handle of the timer of the first allocated timer that has the
* specified parameter.
*
* @param param - specified parameter of timer
*
* @retval return the handle of the timer if success.
*/
timer_handle_t TM_GetFirstTimerWithParam(void *param)
{
list_element_handle_t list_element;
list_handle_t timerHandle = &s_timermanager.timerHead;
list_element = LIST_GetHead(timerHandle);
while (NULL != list_element)
{
timer_handle_struct_t *th = (timer_handle_struct_t *)(void *)list_element;
if (th->param == param)
{
return th;
}
list_element = LIST_GetNext(list_element);
}
return NULL;
}
/*!
* @brief Returns not counted time before entering in sleep,This function is called
* by Low Power module;
*
* @retval return microseconds that wasn't counted before entering in sleep.
*/
uint32_t TM_NotCountedTimeBeforeSleep(void)
{
uint32_t timeUs = 0;
#if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
uint32_t currentTimeInUs;
if (0U != s_timermanager.numberOfLowPowerActiveTimers)
{
currentTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
HAL_TimerDisable((hal_timer_handle_t)s_timermanager.halTimerHandle);
s_timermanager.timerHardwareIsRunning = 0U;
/* The hw timer is stopped but keep s_timermanager.timerHardwareIsRunning = TRUE...*/
/* The Lpm timers are considered as being in running mode, so that */
/* not to start the hw timer if a TMR event occurs (this shouldn't happen) */
timeUs = (uint32_t)(currentTimeInUs - s_timermanager.previousTimeInUs);
return timeUs;
}
return 0;
#endif
}
/*!
* @brief Sync low power timer in sleep mode,This function is called by Low Power module;
*
* @param sleepDurationTmrUs - sleep duration in TMR microseconds
*
*/
void TM_SyncLpmTimers(uint32_t sleepDurationTmrUs)
{
#if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
TimersUpdateSyncTask(sleepDurationTmrUs);
HAL_TimerEnable((hal_timer_handle_t)s_timermanager.halTimerHandle);
s_timermanager.previousTimeInUs = HAL_TimerGetCurrentTimerCount((hal_timer_handle_t)s_timermanager.halTimerHandle);
#else
sleepDurationTmrUs = sleepDurationTmrUs;
#endif /* #if (TM_ENABLE_LOW_POWER_TIMER) */
}
/*!
* @brief Make timer task ready after wakeup from lowpower mode,This function is called
* by Low Power module;
*
*/
void TM_MakeTimerTaskReady(void)
{
#if (defined(TM_ENABLE_LOW_POWER_TIMER) && (TM_ENABLE_LOW_POWER_TIMER > 0U))
NotifyTimersTask();
#endif
}