aboutsummaryrefslogtreecommitdiffstats
path: root/ucs2-lib/src/ucs_timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'ucs2-lib/src/ucs_timer.c')
-rw-r--r--ucs2-lib/src/ucs_timer.c456
1 files changed, 0 insertions, 456 deletions
diff --git a/ucs2-lib/src/ucs_timer.c b/ucs2-lib/src/ucs_timer.c
deleted file mode 100644
index 6563374..0000000
--- a/ucs2-lib/src/ucs_timer.c
+++ /dev/null
@@ -1,456 +0,0 @@
-/*------------------------------------------------------------------------------------------------*/
-/* UNICENS V2.1.0-3491 */
-/* Copyright (c) 2017 Microchip Technology Germany II GmbH & Co. KG. */
-/* */
-/* This program is free software: you can redistribute it and/or modify */
-/* it under the terms of the GNU General Public License as published by */
-/* the Free Software Foundation, either version 2 of the License, or */
-/* (at your option) any later version. */
-/* */
-/* This program is distributed in the hope that it will be useful, */
-/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
-/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
-/* GNU General Public License for more details. */
-/* */
-/* You should have received a copy of the GNU General Public License */
-/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
-/* */
-/* You may also obtain this software under a propriety license from Microchip. */
-/* Please contact Microchip for further information. */
-/*------------------------------------------------------------------------------------------------*/
-
-/*!
- * \file
- * \brief Implementation of the timer management module.
- *
- * \cond UCS_INTERNAL_DOC
- * \addtogroup G_TIMER
- * @{
- */
-
-/*------------------------------------------------------------------------------------------------*/
-/* Includes */
-/*------------------------------------------------------------------------------------------------*/
-#include "ucs_timer.h"
-#include "ucs_misc.h"
-#include "ucs_trace.h"
-
-/*------------------------------------------------------------------------------------------------*/
-/* Service parameters */
-/*------------------------------------------------------------------------------------------------*/
-/*! Priority of the TM service used by scheduler */
-static const uint8_t TM_SRV_PRIO = 255U; /* parasoft-suppress MISRA2004-8_7 "Value shall be part of the module, not part of a function." */
-/*! Main event for the TM service */
-static const Srv_Event_t TM_EVENT_UPDATE_TIMERS = 1U;
-
-/*------------------------------------------------------------------------------------------------*/
-/* Internal prototypes */
-/*------------------------------------------------------------------------------------------------*/
-static void Tm_Service(void *self);
-static void Tm_UpdateTimers(CTimerManagement *self);
-static bool Tm_HandleElapsedTimer(CTimerManagement *self);
-static bool Tm_UpdateTimersAdd(void *c_timer_ptr, void *n_timer_ptr);
-static void Tm_SetTimerInternal(CTimerManagement *self,
- CTimer *timer_ptr,
- Tm_Handler_t handler_fptr,
- void *args_ptr,
- uint16_t elapse,
- uint16_t period);
-
-/*------------------------------------------------------------------------------------------------*/
-/* Implementation of class CTimerManagement */
-/*------------------------------------------------------------------------------------------------*/
-/*! \brief Constructor of the timer management class.
- * \param self Instance pointer
- * \param scd Scheduler instance
- * \param init_ptr Reference to the initialization data
- * \param ucs_user_ptr User reference that needs to be passed in every callback function
- */
-void Tm_Ctor(CTimerManagement *self, CScheduler *scd, const Tm_InitData_t *init_ptr, void * ucs_user_ptr)
-{
- MISC_MEM_SET(self, 0, sizeof(*self));
- self->ucs_user_ptr = ucs_user_ptr;
- /* Initialize subjects and add observers */
- Ssub_Ctor(&self->get_tick_count_subject, self->ucs_user_ptr);
- (void)Ssub_AddObserver(&self->get_tick_count_subject,
- init_ptr->get_tick_count_obs_ptr);
- if(init_ptr->set_application_timer_obs_ptr != NULL)
- {
- self->delayed_tm_service_enabled = true;
- Ssub_Ctor(&self->set_application_timer_subject, self->ucs_user_ptr);
- (void)Ssub_AddObserver(&self->set_application_timer_subject,
- init_ptr->set_application_timer_obs_ptr);
- }
- /* Initialize timer management service */
- Srv_Ctor(&self->tm_srv, TM_SRV_PRIO, self, &Tm_Service);
- /* Add timer management service to scheduler */
- (void)Scd_AddService(scd, &self->tm_srv);
-}
-
-/*! \brief Service function of the timer management.
- * \param self Instance pointer
- */
-static void Tm_Service(void *self)
-{
- CTimerManagement *self_ = (CTimerManagement *)self;
- Srv_Event_t event_mask;
-
- Srv_GetEvent(&self_->tm_srv, &event_mask);
-
- if(TM_EVENT_UPDATE_TIMERS == (event_mask & TM_EVENT_UPDATE_TIMERS)) /* Is event pending? */
- {
- Srv_ClearEvent(&self_->tm_srv, TM_EVENT_UPDATE_TIMERS);
- Tm_UpdateTimers(self_);
- }
-}
-
-/*! \brief If event TM_EVENT_UPDATE_TIMERS is set this function is called. Handles the update
- * of the timer list. If a timer has expired the corresponding callback function is
- * executed. If the expired timer is a periodic timer, the timer will be set again.
- * \param self Instance pointer
- */
-static void Tm_UpdateTimers(CTimerManagement *self)
-{
- uint16_t current_tick_count;
- Ssub_Notify(&self->get_tick_count_subject, &current_tick_count, false);
-
- if(self->timer_list.head != NULL) /* At least one timer is running? */
- {
- bool continue_loop = true;
- /* Calculate time difference between the current and the last TM service run */
- uint16_t tick_count_diff = (uint16_t)(current_tick_count - self->last_tick_count);
- /* Save current tick count for next service run */
- self->last_tick_count = current_tick_count;
-
- /* Loop while timer list is not empty */
- while((self->timer_list.head != NULL) && (continue_loop!= false))
- {
- /* Is not first timer in list elapsed yet? */
- if(tick_count_diff <= ((CTimer *)self->timer_list.head->data_ptr)->delta)
- {
- /* Update delta of first timer in list */
- ((CTimer *)self->timer_list.head->data_ptr)->delta -= tick_count_diff;
- tick_count_diff = 0U;
- }
- else /* At least first timer in list elapsed */
- {
- /* Update tick count difference for next timer in list */
- tick_count_diff -= ((CTimer *)self->timer_list.head->data_ptr)->delta;
- /* First timer elapsed */
- ((CTimer *)self->timer_list.head->data_ptr)->delta = 0U;
- }
-
- /* First timer in list elapsed? */
- if(0U == ((CTimer *)self->timer_list.head->data_ptr)->delta)
- {
- /* Handle elapsed timer */
- continue_loop = Tm_HandleElapsedTimer(self);
- }
- else /* No elapsed timer in list. */
- {
- /* First timer in list updated! Set trigger to inform application (see
- Tm_CheckForNextService()) and stop TM service. */
- self->set_service_timer = true;
- continue_loop = false;
- }
- }
- }
-}
-
-/*! \brief This function is called if the first timer in list is elapsed. The timer handler
- * callback function is invoked. If the timer is a periodic timer it is wound up again.
- * \param self Instance pointer
- * \return \c true if the next timer must be check.
- * \return \c false if the wound up timer (periodic timer) is new head of timer list
- */
-static bool Tm_HandleElapsedTimer(CTimerManagement *self)
-{
- bool ret_val = true;
-
- CDlNode *node = self->timer_list.head;
- /* Reset flag to be able to check if timer object has changed within handler
- callback function */
- ((CTimer *)node->data_ptr)->changed = false;
- /* Call timer handler callback function */
- ((CTimer *)node->data_ptr)->handler_fptr(((CTimer *)node->data_ptr)->args_ptr);
-
- /* Timer object hasn't changed within handler callback function? */
- if(false == ((CTimer *)node->data_ptr)->changed)
- {
- /* Remove current timer from list */
- (void)Dl_Remove(&self->timer_list, node);
- /* Mark timer as unused */
- ((CTimer *)node->data_ptr)->in_use = false;
- /* Is current timer a periodic timer? */
- if(((CTimer *)node->data_ptr)->period > 0U)
- {
- /* Reload current timer */
- Tm_SetTimerInternal(self,
- ((CTimer *)node->data_ptr),
- ((CTimer *)node->data_ptr)->handler_fptr,
- ((CTimer *)node->data_ptr)->args_ptr,
- ((CTimer *)node->data_ptr)->period,
- ((CTimer *)node->data_ptr)->period);
-
- if(node == self->timer_list.head) /* Is current timer new head of list? */
- {
- /* Set trigger to inform application (see Tm_CheckForNextService()) and
- stop TM service. */
- self->set_service_timer = true;
- ret_val = false;
- }
- }
- }
-
- return ret_val;
-}
-
-/*! \brief Calls an application callback function to inform the application that the UCS must be
- * serviced not later than the passed time period. If the timer list is empty a possible
- * running application timer will be stopped. This function is called at the end of
- * Ucs_Service().
- * \param self Instance pointer
- */
-void Tm_CheckForNextService(CTimerManagement *self)
-{
- if(self->delayed_tm_service_enabled != false)
- {
- uint16_t current_tick_count;
- Ssub_Notify(&self->get_tick_count_subject, &current_tick_count, false);
- /* Has head of timer list changed? */
- if(self->set_service_timer != false)
- {
- uint16_t new_time;
- uint16_t diff = current_tick_count - self->last_tick_count;
- self->set_service_timer = false;
- if (self->timer_list.head != NULL)
- {
- /* Timer expired since last TM service? */
- if(diff >= ((CTimer *)self->timer_list.head->data_ptr)->delta)
- {
- new_time = 1U; /* Return minimum value */
- }
- else
- {
- /* Calculate new timeout */
- new_time = (uint16_t)(((CTimer *)self->timer_list.head->data_ptr)->delta - diff);
- }
- /* Inform the application that the UCS must be serviced not later than the passed
- time period. */
- Ssub_Notify(&self->set_application_timer_subject, &new_time, false);
- }
- }
- }
- else
- {
- Tm_TriggerService(self); /* Application timer not implemented -> Retrigger TM */
- }
-}
-
-/*! \brief Helper function to set the TM service event.
- * \details This function is used by the application to trigger a service call of the Timer
- * Management if the application timer has expired.
- * \param self Instance pointer
- */
-void Tm_TriggerService(CTimerManagement *self)
-{
- if(self->timer_list.head != NULL) /* At least one timer is running? */
- {
- Srv_SetEvent(&self->tm_srv, TM_EVENT_UPDATE_TIMERS);
- }
-}
-
-/*! \brief Helper function to stop the TM service.
- * \param self Instance pointer
- */
-void Tm_StopService(CTimerManagement *self)
-{
- uint16_t new_time = 0U;
-
- /* Clear probable running application timer */
- Ssub_Notify(&self->set_application_timer_subject, &new_time, false);
-
- /* Reset the service timer. Not necessary ? */
- self->set_service_timer = false;
-
- /* Clear the timer head queue to prevent any event to be set */
- self->timer_list.head = NULL;
-}
-
-/*! \brief Creates a new timer. The timer expires at the specified elapse time and then after
- * every specified period. When the timer expires the specified callback function is
- * called.
- * \param self Instance pointer
- * \param timer_ptr Reference to the timer object
- * \param handler_fptr Callback function which is called when the timer expires
- * \param args_ptr Reference to an optional parameter which is passed to the specified
- * callback function
- * \param elapse The elapse value before the timer expires for the first time, in
- * milliseconds
- * \param period The period of the timer, in milliseconds. If this parameter is zero, the
- * timer is signaled once. If the parameter is greater than zero, the timer
- * is periodic.
- */
-void Tm_SetTimer(CTimerManagement *self,
- CTimer *timer_ptr,
- Tm_Handler_t handler_fptr,
- void *args_ptr,
- uint16_t elapse,
- uint16_t period)
-{
- (void)Tm_ClearTimer(self, timer_ptr); /* Clear timer if running */
- /* Call the internal method to set the new timer (-> does not trigger TM service!) */
- Tm_SetTimerInternal(self, timer_ptr, handler_fptr, args_ptr, elapse, period);
- Tm_TriggerService(self); /* New timer added -> trigger timer list update */
-}
-
-/*! \brief This function contains the internal part when adding a new timer. The function is
- * called within Tm_SetTimer() and within Tm_UpdateTimers().
- * \param self Instance pointer
- * \param timer_ptr Reference to the timer object
- * \param handler_fptr Callback function which is called when the timer expires
- * \param args_ptr Reference to an optional parameter which is passed to the specified
- * callback function
- * \param elapse The elapse value before the timer expires for the first time, in
- * milliseconds
- * \param period The period of the timer, in milliseconds. If this parameter is zero, the
- * timer is signaled once. If the parameter is greater than zero, the timer
- * is periodic.
- */
-static void Tm_SetTimerInternal(CTimerManagement *self,
- CTimer *timer_ptr,
- Tm_Handler_t handler_fptr,
- void *args_ptr,
- uint16_t elapse,
- uint16_t period)
-{
- uint16_t current_tick_count;
- Ssub_Notify(&self->get_tick_count_subject, &current_tick_count, false);
-
- /* Save timer specific values */
- timer_ptr->changed = true; /* Flag is needed by Tm_UpdateTimers() */
- timer_ptr->in_use = true;
- timer_ptr->handler_fptr = handler_fptr;
- timer_ptr->args_ptr = args_ptr;
- timer_ptr->elapse = elapse;
- timer_ptr->period = period;
- timer_ptr->delta = elapse;
-
- /* Create back link to be able to point from node to timer object */
- timer_ptr->node.data_ptr = (void *)timer_ptr;
-
- if(self->timer_list.head == NULL) /* Is timer list empty? */
- {
- Dl_InsertHead(&self->timer_list, &timer_ptr->node); /* Add first timer to list */
- /* Save current tick count */
- Ssub_Notify(&self->get_tick_count_subject, &self->last_tick_count, false);
- }
- else /* Timer list is not empty */
- {
- CDlNode *result_ptr = NULL;
-
- /* Set delta value in relation to last saved tick count (last TM service) */
- timer_ptr->delta += (uint16_t)(current_tick_count - self->last_tick_count);
-
- /* Search slot where new timer must be inserted. Update delta of new timer
- and delta of the following timer in the list. */
- result_ptr = Dl_Foreach(&self->timer_list, &Tm_UpdateTimersAdd, (void *)timer_ptr);
-
- if(result_ptr != NULL) /* Slot found? */
- {
- /* Insert new timer at found position */
- Dl_InsertBefore(&self->timer_list, result_ptr, &timer_ptr->node);
- }
- else /* No slot found -> Insert as last node */
- {
- /* Add new timer to end of list */
- Dl_InsertTail(&self->timer_list, &timer_ptr->node);
- }
- }
-}
-
-/*! \brief Removes the specified timer from the timer list.
- * \param self Instance pointer
- * \param timer_ptr Reference to the timer object
- * \attention Make sure that for a timer object Tm_SetTimer() is called before Tm_ClearTimer()
- * is called!
- */
-void Tm_ClearTimer(CTimerManagement *self, CTimer *timer_ptr)
-{
- if(timer_ptr->in_use != false) /* Is timer currently in use? */
- {
- timer_ptr->changed = true; /* Flag is needed by Tm_UpdateTimers() */
-
- if(timer_ptr->node.next != NULL) /* Has deleted timer a follower? */
- {
- /* Adjust delta of following timer */
- ((CTimer *)timer_ptr->node.next->data_ptr)->delta += timer_ptr->delta;
- }
-
- (void)Dl_Remove(&self->timer_list, &timer_ptr->node);
- timer_ptr->in_use = false;
-
- Tm_TriggerService(self); /* Timer removed -> trigger timer list update */
- }
-}
-
-/*! \brief Used by Tm_SetTimer() to find the slot where the new timer must be inserted.
- * \param c_timer_ptr Reference to current timer processed by foreach loop
- * \param n_timer_ptr Reference to new timer
- * \return \c true: Slot found, stop foreach loop
- * \return \c false: Slot not found, continue foreach loop
- */
-static bool Tm_UpdateTimersAdd(void *c_timer_ptr, void *n_timer_ptr)
-{
- CTimer *current_timer_ptr = (CTimer *)c_timer_ptr;
- CTimer *new_timer_ptr = (CTimer *)n_timer_ptr;
- bool ret_val;
-
- /* Is current timer lesser than new timer? */
- if(current_timer_ptr->delta <= new_timer_ptr->delta)
- {
- /* Update delta of new timer and continue foreach loop */
- new_timer_ptr->delta -= current_timer_ptr->delta;
- ret_val = false;
- }
- else /* Slot found! */
- {
- /* Correct delta of current timer and stop foreach loop */
- current_timer_ptr->delta -= new_timer_ptr->delta;
- ret_val = true;
- }
-
- return ret_val;
-}
-
-
-/*------------------------------------------------------------------------------------------------*/
-/* Implementation of class CTimer */
-/*------------------------------------------------------------------------------------------------*/
-/*! \brief Constructor of the Timer class.
- * \param self Instance pointer
- */
-void T_Ctor(CTimer *self)
-{
- MISC_MEM_SET(self, 0, sizeof(*self));
-}
-
-/*! \brief Returns the status of the given timer.
- * \param self Instance pointer
- * \return \c true if the timer is currently in use
- * \return \c false if the timer is not currently in use
- */
-bool T_IsTimerInUse(CTimer *self)
-{
- return self->in_use;
-}
-
-/*!
- * @}
- * \endcond
- */
-
-/*------------------------------------------------------------------------------------------------*/
-/* End of file */
-/*------------------------------------------------------------------------------------------------*/
-