0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-06-14 11:22:09 +00:00
Files
2022-01-04 12:22:53 +02:00

2100 lines
70 KiB
C

/*HEADER*********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: timer.c$
* $Version : 3.8.2.0$
* $Date : Jun-25-2012$
*
* Comments:
*
* This file contains functions of the Timer component.
*
*END************************************************************************/
#include "mqx_inc.h"
#if MQX_USE_TIMER
#include "timer.h"
#include "timer_prv.h"
/*!
* \brief Cancels an outstanding timer request.
*
* \param[in] id ID of the timer to be cancelled, from calling a function from
* the _timer_start family of functions.
*
* \return MQX_OK
* \return MQX_COMPONENT_DOES_NOT_EXIST (Timer component is not created.)
* \return MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \return MQX_INVALID_PARAMETER (Id is not valid.)
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_INVALID_LWSEM
*
* \warning Cannot be called from an ISR.
*
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
*/
_mqx_uint _timer_cancel
(
_timer_id id
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
QUEUE_STRUCT_PTR queue_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_timer_cancel, id);
timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_KLOGX2(KLOG_timer_cancel, MQX_COMPONENT_DOES_NOT_EXIST);
return MQX_COMPONENT_DOES_NOT_EXIST;
} /* Endif */
#endif
#if MQX_CHECK_VALIDITY
if (timer_component_ptr->VALID != TIMER_VALID)
{
_KLOGX2(KLOG_timer_cancel, MQX_INVALID_COMPONENT_BASE);
return MQX_INVALID_COMPONENT_BASE;
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (id == 0)
{
_KLOGX2(KLOG_timer_cancel, MQX_INVALID_PARAMETER);
return MQX_INVALID_PARAMETER;
} /* Endif */
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_timer_cancel, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return MQX_CANNOT_CALL_FUNCTION_FROM_ISR;
} /* Endif */
#endif
/* Gain exclusive access to the timer queues */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_KLOGX2(KLOG_timer_cancel, MQX_INVALID_LWSEM);
return(MQX_INVALID_LWSEM);
} /* Endif */
} /*Endif */
timer_entry_ptr = _timer_find_entry_internal(timer_component_ptr, id);
if ((timer_entry_ptr == NULL) || (timer_entry_ptr->VALID != TIMER_VALID))
{
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
_KLOGX2(KLOG_timer_cancel, MQX_INVALID_PARAMETER);
return MQX_INVALID_PARAMETER;
} /* Endif */
if (timer_entry_ptr->MODE == TIMER_ELAPSED_TIME_MODE)
{
queue_ptr = &timer_component_ptr->ELAPSED_TIMER_ENTRIES;
}
else
{
queue_ptr = &timer_component_ptr->KERNEL_TIMER_ENTRIES;
} /* Endif */
timer_entry_ptr->VALID = 0;
timer_entry_ptr->ID = 0;
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_QUEUE_REMOVE(queue_ptr, timer_entry_ptr);
_mem_free(timer_entry_ptr);
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
_KLOGX2(KLOG_timer_cancel, MQX_OK);
return(MQX_OK);
} /* Endbody */
/*!
* \private
*
* \brief Locates a timer via its ID.
*
* \param[in] timer_component_ptr The address of the timer component structure.
* \param[in] id The timer ID.
*
* \return Pointer to a timer entry.
* \return NULL (failure)
*/
TIMER_ENTRY_STRUCT_PTR _timer_find_entry_internal
(
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr,
_timer_id id
)
{ /* Body */
QUEUE_STRUCT_PTR queue_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
_mqx_uint i;
_mqx_uint size;
for (i = 0; i < 2; i++)
{
if (i == 0)
{
queue_ptr = &timer_component_ptr->ELAPSED_TIMER_ENTRIES;
}
else
{
queue_ptr = &timer_component_ptr->KERNEL_TIMER_ENTRIES;
} /* Endif */
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)((pointer)queue_ptr->NEXT);
/* SPR P171-0023-01 use pre-decrement on while loop */
size = queue_ptr->SIZE + 1;
while (--size)
{
/* END SPR */
if (timer_entry_ptr->ID == id)
{
return(timer_entry_ptr);
} /* Endif */
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)
((pointer)timer_entry_ptr->QUEUE_ELEMENT.NEXT);
} /* Endwhile */
} /* Endfor */
return(NULL);
} /* Endbody */
/*!
* \brief Istalls the timer component into the kernel.
*
* If the timer component is not explicitly created, MQX creates it with default
* values the first time that a task calls one of the functions from the
* _timer_start family.
* \n The default values are:
* \li TIMER_DEFAULT_TASK_PRIORITY
* \li TIMER_DEFAULT_STACK_SIZE
*
* \n The function returns MQX_OK if either:
* \li Timer component is created.
* \li Timer component was previously created and the configuration is not changed.
*
* \param[in] timer_task_priority The task priority of the timer task.
* \param[in] timer_task_stack_size The stack size for the timer task.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \return task error codes
*
* \warning Creates Timer Task.
* \warning Cannot be called from an ISR.
*
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _timer_cancel
*/
_mqx_uint _timer_create_component
(
_mqx_uint timer_task_priority,
_mqx_uint timer_task_stack_size
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TASK_TEMPLATE_STRUCT timer_tt;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_timer_create_component, timer_task_priority);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_timer_create_component, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
_lwsem_wait((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM);
if (kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER] != NULL)
{
_lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_timer_create_component, MQX_OK);
return(MQX_OK);
} /* Endif */
/* Get the timer component data structure */
timer_component_ptr = _mem_alloc_system_zero((_mem_size)sizeof(TIMER_COMPONENT_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (timer_component_ptr == NULL)
{
_lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_timer_create_component, MQX_OUT_OF_MEMORY);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(timer_component_ptr, MEM_TYPE_TIMER_COMPONENT);
_QUEUE_INIT(&timer_component_ptr->ELAPSED_TIMER_ENTRIES, 0);
_QUEUE_INIT(&timer_component_ptr->KERNEL_TIMER_ENTRIES, 0);
timer_tt.TASK_TEMPLATE_INDEX = 0;
timer_tt.TASK_ADDRESS = _timer_task;
if (timer_task_stack_size == 0)
{
timer_tt.TASK_STACKSIZE = TIMER_DEFAULT_STACK_SIZE;
}
else
{
timer_tt.TASK_STACKSIZE = timer_task_stack_size;
} /* Endif */
if (timer_task_priority == 0)
{
timer_tt.TASK_PRIORITY = TIMER_DEFAULT_TASK_PRIORITY;
}
else
{
timer_tt.TASK_PRIORITY = timer_task_priority;
} /* Endif */
timer_tt.TASK_NAME = "Timer Task";
timer_tt.TASK_ATTRIBUTES = 0;
timer_tt.DEFAULT_TIME_SLICE = 0;
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER] = timer_component_ptr;
timer_component_ptr->TIMER_TID = _task_create(0, 0, (uint_32)&timer_tt);
#if MQX_CHECK_ERRORS
if (timer_component_ptr->TIMER_TID == MQX_NULL_TASK_ID)
{
_mqx_uint result;
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER] = NULL;
timer_component_ptr->VALID = 0;
result = _task_get_error();
if (result == MQX_OK)
{
result = MQX_OUT_OF_MEMORY;
} /* Endif */
_lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM);
_mem_free(timer_component_ptr);
_KLOGX2(KLOG_timer_create_component, result);
return(result);
}/* Endif */
#endif
#if MQX_COMPONENT_DESTRUCTION
kernel_data->COMPONENT_CLEANUP[KERNEL_EVENTS] = _timer_cleanup;
#endif
_lwsem_post((LWSEM_STRUCT_PTR)&kernel_data->COMPONENT_CREATE_LWSEM);
_KLOGX2(KLOG_timer_create_component, MQX_OK);
return(MQX_OK);
} /* Endbody */
/*!
* \private
*
* \brief Initializes a timer to start once after a delay period expressed in ticks.
*
* \param[in] notification_function_ptr The function to call when the timer expires.
* \param[in] notification_data_ptr The data to pass to the function when
* the timer expires.
* \param[in] mode Which time to use when calculating time
* to start:
* \li TIMER_ElAPSED_TIME_MODE
* \li TIMER_KERNEL_TIME_MODE
* \param[in] tick_ptr The number of ticks to wait before calling
* the notification function, and canceling the timer.
* \param[in] uses_ticks Set to true if called from the tick
* interface functions.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*/
_timer_id _timer_start_oneshot_after_internal
(
TIMER_NOTIFICATION_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR tick_ptr,
boolean uses_ticks
)
{
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
MQX_TICK_STRUCT kernel_time;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
result = _timer_create_component(TIMER_DEFAULT_TASK_PRIORITY,
TIMER_DEFAULT_STACK_SIZE);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_task_set_error(result);
return TIMER_NULL_ID;
} /* Endif */
#endif
}/* Endif */
#if MQX_CHECK_VALIDITY
if (timer_component_ptr->VALID != TIMER_VALID)
{
_task_set_error(MQX_INVALID_COMPONENT_BASE);
return TIMER_NULL_ID;
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if ((notification_function_ptr == NULL) ||
! ((mode == TIMER_ELAPSED_TIME_MODE) || (mode == TIMER_KERNEL_TIME_MODE))
)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
result = (_mqx_uint)PSP_CMP_TICKS(&_mqx_zero_tick_struct, tick_ptr);
if (result == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
#endif
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(TIMER_ENTRY_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (timer_entry_ptr == NULL)
{
_task_set_error(MQX_OUT_OF_MEMORY);
return TIMER_NULL_ID;
} /* Endif */
#endif
_mem_set_type(timer_entry_ptr, MEM_TYPE_TIMER_ENTRY);
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_time_get_elapsed_ticks(&kernel_time);
}
else
{
_time_get_ticks(&kernel_time);
} /* Endif */
PSP_ADD_TICKS(tick_ptr, &kernel_time, &timer_entry_ptr->EXPIRATION_TIME);
timer_entry_ptr->NOTIFICATION_FUNCTION = notification_function_ptr;
timer_entry_ptr->NOTIFICATION_DATA_PTR = notification_data_ptr;
timer_entry_ptr->MODE = (uint_16)mode;
timer_entry_ptr->TIMER_TYPE = TIMER_TYPE_ONESHOT_AFTER;
timer_entry_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
timer_entry_ptr->USES_TICKS = uses_ticks;
/* Gain exclusive access to the timer queues */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
return(TIMER_NULL_ID);
} /* Endif */
} /* Endif */
timer_entry_ptr->VALID = TIMER_VALID;
timer_entry_ptr->ID = _timer_alloc_id_internal(timer_component_ptr);
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_timer_insert_queue_internal(&timer_component_ptr->ELAPSED_TIMER_ENTRIES,
timer_entry_ptr);
}
else
{
_timer_insert_queue_internal(&timer_component_ptr->KERNEL_TIMER_ENTRIES,
timer_entry_ptr);
} /* Endif */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
return(timer_entry_ptr->ID);
} /* Endbody */
/*!
* \brief Starts a timer that expires after the specified number of ticks (in tick
* time).
*
* The function calculates the expiry time based on tick_ptr and mode.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Notification function that MQX calls when
* the timer expires.
* \param[in] notification_data_ptr The data to pass to the notification
* function when the timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] tick_ptr The number of ticks to wait before calling
* the notification function, and canceling the timer.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_oneshot_after
* \see _task_set_error
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _time_get
* \see _time_get_ticks
* \see _time_set
* \see _time_set_ticks
* \see _timer_cancel
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _timer_create_component
*/
_timer_id _timer_start_oneshot_after_ticks
(
TIMER_NOTIFICATION_TICK_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR tick_ptr
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_oneshot_after_ticks, notification_function_ptr,
mode, tick_ptr);
#if MQX_CHECK_ERRORS
if (tick_ptr == NULL)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_oneshot_after_ticks, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
result = _timer_start_oneshot_after_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, tick_ptr, TRUE);
_KLOGX2(KLOG_timer_start_oneshot_after_ticks, result);
return result;
} /* Endbody */
/*!
* \private
*
* \brief Initializes a timer to start once at a specified time.
*
* \param[in] notification_function_ptr The function to call when the timer expires.
* \param[in] notification_data_ptr The data to pass to the function when
* the timer expires.
* \param[in] mode Which time to use when calculating time
* to start:
* \li TIMER_ElAPSED_TIME_MODE
* \li TIMER_KERNEL_TIME_MODE
* \param[in] tick_ptr The time at which to call the notification
* function, and then cancel the timer.
* \param[in] uses_ticks Set to true if notification function
* uses ticks.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*/
_timer_id _timer_start_oneshot_at_internal
(
TIMER_NOTIFICATION_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR tick_ptr,
boolean uses_ticks
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
_mqx_uint error;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
error = _timer_create_component(TIMER_DEFAULT_TASK_PRIORITY,
TIMER_DEFAULT_STACK_SIZE);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_task_set_error(error);
return TIMER_NULL_ID;
} /* Endif */
#endif
}/* Endif */
#if MQX_CHECK_VALIDITY
if (timer_component_ptr->VALID != TIMER_VALID)
{
_task_set_error(MQX_INVALID_COMPONENT_BASE);
return TIMER_NULL_ID;
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if ((notification_function_ptr == NULL) ||
! ((mode == TIMER_ELAPSED_TIME_MODE) || (mode == TIMER_KERNEL_TIME_MODE))
)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
error = (_mqx_uint)PSP_CMP_TICKS(&_mqx_zero_tick_struct, tick_ptr);
if (error == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
#endif
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(TIMER_ENTRY_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (timer_entry_ptr == NULL)
{
_task_set_error(MQX_OUT_OF_MEMORY);
return TIMER_NULL_ID;
} /* Endif */
#endif
_mem_set_type(timer_entry_ptr, MEM_TYPE_TIMER_ENTRY);
timer_entry_ptr->NOTIFICATION_FUNCTION = notification_function_ptr;
timer_entry_ptr->NOTIFICATION_DATA_PTR = notification_data_ptr;
timer_entry_ptr->MODE = (uint_16)mode;
timer_entry_ptr->TIMER_TYPE = TIMER_TYPE_ONESHOT_AT;
timer_entry_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
timer_entry_ptr->USES_TICKS = uses_ticks;
timer_entry_ptr->EXPIRATION_TIME = *tick_ptr;
/* Gain exclusive access to the timer queues */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
return(TIMER_NULL_ID);
} /* Endif */
} /* Endif */
timer_entry_ptr->VALID = TIMER_VALID;
timer_entry_ptr->ID = _timer_alloc_id_internal(timer_component_ptr);
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_timer_insert_queue_internal(&timer_component_ptr->ELAPSED_TIMER_ENTRIES,
timer_entry_ptr);
}
else
{
_timer_insert_queue_internal(&timer_component_ptr->KERNEL_TIMER_ENTRIES,
timer_entry_ptr);
} /* Endif */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
return(timer_entry_ptr->ID);
} /* Endbody */
/*!
* \brief Starts a timer that expire once at the specified time in tick time.
*
* When the timer expires, MQX calls notification_function with timer_id,
* notification_data_ptr, and the current time.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr The data to pass to the function when the
* timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] tick_ptr Pointer to the tick time at which MQX
* calls the notification function and cancels the timer.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_oneshot_at
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_oneshot_at_ticks
(
TIMER_NOTIFICATION_TICK_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR tick_ptr
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_oneshot_at_ticks, notification_function_ptr, mode,
tick_ptr);
#if MQX_CHECK_ERRORS
if (tick_ptr == NULL)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_oneshot_at_ticks, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
result = _timer_start_oneshot_at_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, tick_ptr, TRUE);
_KLOGX2(KLOG_timer_start_oneshot_at_ticks, result);
return(result);
} /* Endbody */
/*!
* \private
*
* \brief Initializes a timer to fire periodically at a specific time.
*
* \param[in] notification_function_ptr The function to call when the timer expires.
* \param[in] notification_data_ptr The data to pass to the function when
* the timer expires.
* \param[in] mode Which time to use when calculating time
* to start:
* \li TIMER_ElAPSED_TIME_MODE
* \li TIMER_KERNEL_TIME_MODE
* \param[in] stick_ptr The time at which to call the notification
* function, and then cancel the timer.
* \param[in] wtick_ptr The number of ticks to wait between calls
* to the notification function.
* \param[in] uses_ticks Set to true if notification function
* uses ticks.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*/
_timer_id _timer_start_periodic_at_internal
(
TIMER_NOTIFICATION_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR stick_ptr,
MQX_TICK_STRUCT_PTR wtick_ptr,
boolean uses_ticks
)
{
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
result = _timer_create_component(TIMER_DEFAULT_TASK_PRIORITY,
TIMER_DEFAULT_STACK_SIZE);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_task_set_error(result);
return TIMER_NULL_ID;
} /* Endif */
#endif
}/* Endif */
#if MQX_CHECK_VALIDITY
if (timer_component_ptr->VALID != TIMER_VALID)
{
_task_set_error(MQX_INVALID_COMPONENT_BASE);
return TIMER_NULL_ID;
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (!notification_function_ptr ||
! ((mode == TIMER_ELAPSED_TIME_MODE) || (mode == TIMER_KERNEL_TIME_MODE))
)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
result = (_mqx_uint)PSP_CMP_TICKS(&_mqx_zero_tick_struct, wtick_ptr);
if (result == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
#endif
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(TIMER_ENTRY_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (timer_entry_ptr == NULL)
{
_task_set_error(MQX_OUT_OF_MEMORY);
return TIMER_NULL_ID;
} /* Endif */
#endif
_mem_set_type(timer_entry_ptr, MEM_TYPE_TIMER_ENTRY);
timer_entry_ptr->NOTIFICATION_FUNCTION = notification_function_ptr;
timer_entry_ptr->NOTIFICATION_DATA_PTR = notification_data_ptr;
timer_entry_ptr->MODE = (uint_16)mode;
timer_entry_ptr->TIMER_TYPE = TIMER_TYPE_PERIODIC_AT;
timer_entry_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
timer_entry_ptr->USES_TICKS = uses_ticks;
timer_entry_ptr->EXPIRATION_TIME = *stick_ptr;
timer_entry_ptr->CYCLE = *wtick_ptr;
/* Gain exclusive access to the timer queues */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
return(TIMER_NULL_ID);
} /* Endif */
} /* Endif */
timer_entry_ptr->VALID = TIMER_VALID;
timer_entry_ptr->ID = _timer_alloc_id_internal(timer_component_ptr);
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_timer_insert_queue_internal(&timer_component_ptr->ELAPSED_TIMER_ENTRIES,
timer_entry_ptr);
}
else
{
_timer_insert_queue_internal(&timer_component_ptr->KERNEL_TIMER_ENTRIES,
timer_entry_ptr);
} /* Endif */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
return(timer_entry_ptr->ID);
} /* Endbody */
/*!
* \brief Starts a periodic timer at the specified time in tick time.
*
* You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr The data to pass to the function when the
* timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] stick_ptr Pointer to the tick time at which MQX
* starts calling the notification function.
* \param[in] wtick_ptr Ticks (in tick time) that MQX waits
* between subsequent calls to the notification function.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_periodic_at
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_periodic_at_ticks
(
TIMER_NOTIFICATION_TICK_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR stick_ptr,
MQX_TICK_STRUCT_PTR wtick_ptr
)
{ /* Body */
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_periodic_at_ticks, notification_function_ptr, mode,
stick_ptr);
#if MQX_CHECK_ERRORS
if ((notification_function_ptr == NULL) ||
(stick_ptr == NULL) ||
(wtick_ptr == NULL))
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_periodic_at_ticks, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
result = _timer_start_periodic_at_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, stick_ptr, wtick_ptr, TRUE);
_KLOGX2(KLOG_timer_start_periodic_at_ticks, result);
return(result);
} /* Endbody */
/*!
* \private
*
* \brief Initializes a timer to fire periodically.
*
* \param[in] notification_function_ptr The function to call when the timer expires.
* \param[in] notification_data_ptr The data to pass to the function when
* the timer expires.
* \param[in] mode Which time to use when calculating time
* to start:
* \li TIMER_ElAPSED_TIME_MODE
* \li TIMER_KERNEL_TIME_MODE
* \param[in] wtick_ptr The number of ticks to wait before calling
* the notification function.
* \param[in] uses_ticks Set to true if called from the tick
* interface functions.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*/
_timer_id _timer_start_periodic_every_internal
(
TIMER_NOTIFICATION_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR wtick_ptr,
boolean uses_ticks
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
MQX_TICK_STRUCT kernel_time;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
result = _timer_create_component(TIMER_DEFAULT_TASK_PRIORITY,
TIMER_DEFAULT_STACK_SIZE);
timer_component_ptr = (TIMER_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_task_set_error(result);
return TIMER_NULL_ID;
} /* Endif */
#endif
}/* Endif */
#if MQX_CHECK_VALIDITY
if (timer_component_ptr->VALID != TIMER_VALID)
{
_task_set_error(MQX_INVALID_COMPONENT_BASE);
return TIMER_NULL_ID;
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (!notification_function_ptr || !((mode == TIMER_ELAPSED_TIME_MODE) ||
(mode == TIMER_KERNEL_TIME_MODE)) )
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
result = (_mqx_uint)PSP_CMP_TICKS(&_mqx_zero_tick_struct, wtick_ptr);
if (result == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
return TIMER_NULL_ID;
} /* Endif */
#endif
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(TIMER_ENTRY_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (timer_entry_ptr == NULL)
{
return TIMER_NULL_ID;
} /* Endif */
#endif
_mem_set_type(timer_entry_ptr, MEM_TYPE_TIMER_ENTRY);
timer_entry_ptr->CYCLE = *wtick_ptr;
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_time_get_elapsed_ticks(&kernel_time);
}
else
{
_time_get_ticks(&kernel_time);
} /* Endif */
timer_entry_ptr->NOTIFICATION_FUNCTION = notification_function_ptr;
timer_entry_ptr->NOTIFICATION_DATA_PTR = notification_data_ptr;
timer_entry_ptr->MODE = (uint_16)mode;
timer_entry_ptr->USES_TICKS = uses_ticks;
timer_entry_ptr->TIMER_TYPE = TIMER_TYPE_PERIODIC_EVERY;
PSP_ADD_TICKS(wtick_ptr, &kernel_time, &timer_entry_ptr->EXPIRATION_TIME);
timer_entry_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
/* Gain exclusive access to the timer queues */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
return(TIMER_NULL_ID);
} /* Endif */
} /* Endif */
timer_entry_ptr->VALID = TIMER_VALID;
timer_entry_ptr->ID = _timer_alloc_id_internal(timer_component_ptr);
if (mode == TIMER_ELAPSED_TIME_MODE)
{
_timer_insert_queue_internal(&timer_component_ptr->ELAPSED_TIMER_ENTRIES,
timer_entry_ptr);
}
else
{
_timer_insert_queue_internal(&timer_component_ptr->KERNEL_TIMER_ENTRIES,
timer_entry_ptr);
} /* Endif */
if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endif */
return(timer_entry_ptr->ID);
} /* Endbody */
/*!
* \brief Starts a periodic timer every specified number of ticks (in tick time).
*
* When the timer expires, MQX calls notification_function with timer_id, notifier
* data, and the current time.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr Pointer to the data that MQX passes to
* the notification function.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] wtick_ptr Ticks (in tick time) that MQX waits before
* it first calls the notification function and between subsequent calls to the
* notification function.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_periodic_every
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _time_get
* \see _time_get_ticks
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_periodic_every_ticks
(
TIMER_NOTIFICATION_TICK_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
MQX_TICK_STRUCT_PTR wtick_ptr
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_periodic_every_ticks, notification_function_ptr,
mode, wtick_ptr);
#if MQX_CHECK_ERRORS
if ((notification_function_ptr == NULL) || (wtick_ptr == NULL))
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_periodic_every_ticks, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
result = _timer_start_periodic_every_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, wtick_ptr, TRUE);
_KLOGX2(KLOG_timer_start_periodic_every_ticks, result);
return(result);
} /* Endbody */
/*!
* \brief Starts a timer that expire after the specified number of milliseconds.
*
* The function calculates the expiry time based on tick_ptr and mode.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Notification function that MQX calls when
* the timer expires.
* \param[in] notification_data_ptr The data to pass to the notification
* function when the timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] milliseconds Milliseconds to wait before MQX calls the
* notification function and cancels the timer.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_oneshot_after_ticks
* \see _task_set_error
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _time_get
* \see _time_get_ticks
* \see _time_set
* \see _time_set_ticks
* \see _timer_cancel
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _timer_create_component
*/
_timer_id _timer_start_oneshot_after
(
TIMER_NOTIFICATION_TIME_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
uint_32 milliseconds
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
MQX_TICK_STRUCT ticks;
/* TIME_STRUCT time; */
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_oneshot_after, notification_function_ptr, mode,
milliseconds);
#if MQX_CHECK_ERRORS
if (milliseconds == 0)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_oneshot_after, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
/* time.SECONDS = 0; */
/* time.MILLISECONDS = milliseconds; */
/* */
/* PSP_TIME_TO_TICKS(&time, &ticks); */
PSP_MILLISECONDS_TO_TICKS_QUICK(milliseconds, &ticks);
result = _timer_start_oneshot_after_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, (MQX_TICK_STRUCT_PTR)&ticks, FALSE);
_KLOGX2(KLOG_timer_start_oneshot_after, result);
return result;
} /* Endbody */
/*!
* \brief Starts a timer that expire once at the specified time in
* second/millisecond time.
*
* When the timer expires, MQX calls notification_function with timer_id,
* notification_data_ptr, and the current time.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr The data to pass to the function when the
* timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] time_ptr Pointer to the normalized second/millisecond
* time at which MQX calls the notification function and cancels the timer.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_oneshot_at_ticks
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_oneshot_at
(
TIMER_NOTIFICATION_TIME_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
TIME_STRUCT_PTR time_ptr
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
MQX_TICK_STRUCT ticks;
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_oneshot_at, notification_function_ptr, mode, time_ptr);
#if MQX_CHECK_ERRORS
if (time_ptr == NULL)
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_oneshot_at, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
PSP_TIME_TO_TICKS(time_ptr, &ticks);
result = _timer_start_oneshot_at_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, (MQX_TICK_STRUCT_PTR)&ticks, FALSE);
_KLOGX2(KLOG_timer_start_oneshot_at, result);
return(result);
} /* Endbody */
/*!
* \brief Starts a periodic timer at the specified time in second/millisecond time.
*
* You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr The data to pass to the function when the
* timer expires.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] time_ptr Pointer to the normalized second/millisecond
* time at which MQX starts calling the notification function.
* \param[in] milliseconds Milliseconds that MQX waits between
* subsequent calls to the notification function.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_periodic_at_ticks
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_periodic_at
(
TIMER_NOTIFICATION_TIME_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
TIME_STRUCT_PTR time_ptr,
uint_32 milliseconds
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
MQX_TICK_STRUCT stick;
MQX_TICK_STRUCT wtick;
/* TIME_STRUCT wtime; */
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_periodic_at, notification_function_ptr, mode,
time_ptr);
#if MQX_CHECK_ERRORS
if ((notification_function_ptr == NULL) ||
(time_ptr == NULL) ||
(milliseconds == 0))
{
_task_set_error(MQX_INVALID_PARAMETER);
_KLOGX2(KLOG_timer_start_periodic_at, TIMER_NULL_ID);
return TIMER_NULL_ID;
} /* Endif */
#endif
PSP_TIME_TO_TICKS(time_ptr, &stick);
/* wtime.SECONDS = 0; */
/* wtime.MILLISECONDS = milliseconds; */
/* */
/* PSP_TIME_TO_TICKS(&wtime, &wtick); */
PSP_MILLISECONDS_TO_TICKS_QUICK(milliseconds, &wtick);
result = _timer_start_periodic_at_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, (MQX_TICK_STRUCT_PTR)&stick,
(MQX_TICK_STRUCT_PTR)&wtick, FALSE);
_KLOGX2(KLOG_timer_start_periodic_at, result);
return(result);
} /* Endbody */
/*!
* \brief Starts a periodic timer every specified number of milliseconds.
*
* When the timer expires, MQX calls notification_function with timer_id, notifier
* data, and the current time.
* \n You might need to increase the Timer Task stack size to accommodate the
* notification function (see _timer_create_component()).
*
* \param[in] notification_function_ptr Pointer to the notification function that
* MQX calls when the timer expire.
* \param[in] notification_data_ptr Pointer to the data that MQX passes to
* the notification function.
* \param[in] mode Time to use when calculating the time to
* expire; one of the following:
* \li TIMER_ELAPSED_TIME_MODE (Use _time_get_elapsed() or _time_get_elapsed_ticks(),
* which are not affected by _time_set() or _time_set_ticks().)
* \li TIMER_KERNEL_TIME_MODE (Use _time_get() or _time_get_ticks().)
* \param[in] milliseconds Milliseconds that MQX waits before it
* first calls the notification function and between subsequent calls to the
* notification function.
*
* \return Timer ID (success)
* \return TIMER_NULL_ID (failure)
*
* \warning Creates the timer component with default values if it was not
* previously created.
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_COMPONENT_BASE (Timer component data is no longer valid.)
* \li MQX_INVALID_PARAMETER (One of the following: mode is not one of the
* allowed modes, notification_function is NULL, milliseconds is 0 or
* tick_time_ptr is NULL.)
* \li MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the timer data.)
* \li MQX_INVALID_LWSEM
* \li return code from _timer_create_component()
*
* \see _timer_start_periodic_every_ticks
* \see _timer_cancel
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _time_get
* \see _time_get_ticks
* \see _time_get_elapsed
* \see _time_get_elapsed_ticks
* \see _task_set_error
* \see _timer_create_component
*/
_timer_id _timer_start_periodic_every
(
TIMER_NOTIFICATION_TIME_FPTR notification_function_ptr,
pointer notification_data_ptr,
_mqx_uint mode,
uint_32 milliseconds
)
{
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
MQX_TICK_STRUCT wticks;
/* TIME_STRUCT wtime; */
_timer_id result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE4(KLOG_timer_start_periodic_every, notification_function_ptr, mode,
milliseconds);
/* wtime.SECONDS = 0; */
/* wtime.MILLISECONDS = milliseconds; */
/* */
/* PSP_TIME_TO_TICKS(&wtime, &wticks); */
PSP_MILLISECONDS_TO_TICKS_QUICK(milliseconds, &wticks);
result = _timer_start_periodic_every_internal((TIMER_NOTIFICATION_FPTR)notification_function_ptr,
notification_data_ptr, mode, (MQX_TICK_STRUCT_PTR)&wticks, FALSE);
_KLOGX2(KLOG_timer_start_periodic_every, result);
return(result);
} /* Endbody */
/*!
* \brief This task runs the timer queues, calling the notification functions as
* required.
*
* \param[in] fake_parameter Fake parameter.
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li MQX_INVALID_LWSEM
*/
void _timer_task
(
uint_32 fake_parameter
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
QUEUE_STRUCT_PTR queue_ptrs[2];
QUEUE_STRUCT_PTR queue_ptr;
#if MQX_TIMER_USES_TICKS_ONLY==0
TIME_STRUCT time;
#endif
MQX_TICK_STRUCT ticks;
_mqx_uint i;
_mqx_int result;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
_task_block();
} /* Endif */
#endif
timer_component_ptr->TIMER_TD_PTR = kernel_data->ACTIVE_PTR;
_QUEUE_INIT(&timer_component_ptr->ELAPSED_TIMER_ENTRIES, 0);
_QUEUE_INIT(&timer_component_ptr->KERNEL_TIMER_ENTRIES, 0);
_lwsem_create(&timer_component_ptr->TIMER_ISR_LWSEM, 0);
_lwsem_create(&timer_component_ptr->TIMER_ENTRIES_LWSEM, 1);
timer_component_ptr->VALID = TIMER_VALID;
kernel_data->TIMER_COMPONENT_ISR = _timer_isr;
queue_ptrs[0] = &timer_component_ptr->ELAPSED_TIMER_ENTRIES;
queue_ptrs[1] = &timer_component_ptr->KERNEL_TIMER_ENTRIES;
while (TRUE)
{
for (i = 0; i < 2; ++i)
{
queue_ptr = queue_ptrs[i];
/* Stop tasks from accessing the timer entries table */
if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
_task_block();
} /* Endif */
while (queue_ptr->SIZE > 0)
{
/*
* Check the first entry on the queue to see if it has expired
* Note that entries are always put into the list in sorted order.
*/
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)
((pointer)queue_ptr->NEXT);
if (i == 0)
{
_time_get_elapsed_ticks(&ticks);
}
else
{
_time_get_ticks(&ticks);
} /* Endif */
result = PSP_CMP_TICKS(&timer_entry_ptr->EXPIRATION_TIME, &ticks);
if (result <= 0)
{
/* This entry has expired, remove it from the queue */
_QUEUE_REMOVE(queue_ptr, timer_entry_ptr);
timer_component_ptr->ENTRY_PTR = timer_entry_ptr;
/* fire its notification function */
if (timer_entry_ptr->VALID)
{
#if MQX_TIMER_USES_TICKS_ONLY==0
if (!timer_entry_ptr->USES_TICKS)
{
PSP_TICKS_TO_TIME(&ticks, &time);
(*(TIMER_NOTIFICATION_TIME_FPTR)timer_entry_ptr->NOTIFICATION_FUNCTION)(
timer_entry_ptr->ID,
timer_entry_ptr->NOTIFICATION_DATA_PTR, time.SECONDS,
time.MILLISECONDS);
}
else
{
#endif
(*(TIMER_NOTIFICATION_TICK_FPTR)timer_entry_ptr->NOTIFICATION_FUNCTION)(
timer_entry_ptr->ID,
timer_entry_ptr->NOTIFICATION_DATA_PTR,
(pointer)&ticks);
#if MQX_TIMER_USES_TICKS_ONLY==0
} /* Endif */
#endif
}
/* This entry may be a one-shot, in which case it is to be deleted */
if (IS_ONESHOT(timer_entry_ptr->TIMER_TYPE) ||
(timer_entry_ptr->VALID==0))
{
timer_entry_ptr->VALID = 0;
_mem_free(timer_entry_ptr);
}
else
{
/* Calculate next firing period */
PSP_ADD_TICKS(&timer_entry_ptr->EXPIRATION_TIME,
&timer_entry_ptr->CYCLE,
&timer_entry_ptr->EXPIRATION_TIME);
_timer_insert_queue_internal(queue_ptr, timer_entry_ptr);
}/* Endif */
}
else
{
/* This queue does not require work */
break;
}/* Endif */
} /* Endwhile */
if (_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM) !=
MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
_task_block();
} /* Endif */
} /* Endfor */
/* wait until activation from the kernel timer isr */
if (_lwsem_wait(&timer_component_ptr->TIMER_ISR_LWSEM) != MQX_OK)
{
_task_set_error(MQX_INVALID_LWSEM);
_task_block();
} /* Endif */
} /* Endwhile */
} /* Endbody */
/*!
* \brief Check the timer queues and if a timer is pending schedule the timer
* task to run.
*
* This function is called from the kernel timer ISR.
*
*
*/
void _timer_isr(void)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
MQX_TICK_STRUCT kernel_time;
_mqx_int result;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
#if MQX_CHECK_ERRORS
if (timer_component_ptr == NULL)
{
return;
} /* Endif */
#endif
if (timer_component_ptr->TIMER_TD_PTR->STATE == READY)
{
return;
}/* Endif */
_time_get_elapsed_ticks(&kernel_time);
if (_QUEUE_GET_SIZE(&timer_component_ptr->ELAPSED_TIMER_ENTRIES))
{
timer_entry_ptr = (pointer)timer_component_ptr->ELAPSED_TIMER_ENTRIES.NEXT;
result = PSP_CMP_TICKS(&kernel_time, &timer_entry_ptr->EXPIRATION_TIME);
if (result >= 0)
{
_lwsem_post(&timer_component_ptr->TIMER_ISR_LWSEM);
return;
}/* Endif */
}/* Endif */
if (_QUEUE_GET_SIZE(&timer_component_ptr->KERNEL_TIMER_ENTRIES))
{
PSP_ADD_TICKS(&kernel_time, &kernel_data->TIME_OFFSET, &kernel_time);
timer_entry_ptr = (pointer)timer_component_ptr->KERNEL_TIMER_ENTRIES.NEXT;
result = PSP_CMP_TICKS(&kernel_time, &timer_entry_ptr->EXPIRATION_TIME);
if (result >= 0)
{
_lwsem_post(&timer_component_ptr->TIMER_ISR_LWSEM);
return;
}/* Endif */
}/* Endif */
} /* Endbody */
/*!
* \private
*
* \brief Insert timer_entry_ptr into the queue by time with lowest time first.
*
* \param[in] queue_ptr The queue to insert onto.
* \param[in] timer_entry_ptr The entry to insert into the queue.
*/
void _timer_insert_queue_internal
(
register QUEUE_STRUCT_PTR queue_ptr,
register TIMER_ENTRY_STRUCT_PTR timer_entry_ptr
)
{ /* Body */
/* The element on the queue to start inserting from */
register TIMER_ENTRY_STRUCT_PTR element_ptr;
register TIMER_ENTRY_STRUCT_PTR prev_ptr;
register _mqx_int result;
prev_ptr = NULL;
element_ptr = (pointer)queue_ptr->NEXT;
while (element_ptr != (pointer)queue_ptr)
{
result = PSP_CMP_TICKS(&element_ptr->EXPIRATION_TIME,
&timer_entry_ptr->EXPIRATION_TIME);
if (MQX_DELAY_ENQUEUE_POLICY(result))
{
/* Found the spot to insert it */
break;
}/* Endif */
prev_ptr = element_ptr;
element_ptr = (pointer)element_ptr->QUEUE_ELEMENT.NEXT;
} /* Endwhile */
_queue_insert(queue_ptr, (QUEUE_ELEMENT_STRUCT_PTR)((pointer)prev_ptr),
(QUEUE_ELEMENT_STRUCT_PTR)((pointer)timer_entry_ptr));
} /* Endbody */
/*!
* \private
*
* \brief Create a new timer ID
*
* \param[in] timer_component_ptr The address of the timer component structure.
*
* \return New timer ID.
*/
_timer_id _timer_alloc_id_internal
(
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr
)
{ /* Body */
QUEUE_STRUCT_PTR queue_ptr;
TIMER_ENTRY_STRUCT_PTR timer_entry_ptr;
_timer_id id;
boolean ok;
_mqx_uint i;
_mqx_uint size;
if (timer_component_ptr->ID == 0)
{
timer_component_ptr->ID = 1;
} /* Endif */
id = timer_component_ptr->ID;
/* Make sure ID not in use */
ok = FALSE;
while (!ok)
{
ok = TRUE;
for (i = 0; (i < 2) && ok; i++)
{
if (i == 0)
{
queue_ptr = &timer_component_ptr->ELAPSED_TIMER_ENTRIES;
}
else
{
queue_ptr = &timer_component_ptr->KERNEL_TIMER_ENTRIES;
} /* Endif */
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)((pointer)queue_ptr->NEXT);
/* SPR P171-0023-01 use pre-decrement on while loop */
size = queue_ptr->SIZE + 1;
while (--size)
{
/* END SPR */
if (timer_entry_ptr->ID == id)
{
ok = FALSE;
id++;
break;
} /* Endif */
timer_entry_ptr = (TIMER_ENTRY_STRUCT_PTR)
((pointer)timer_entry_ptr->QUEUE_ELEMENT.NEXT);
} /* Endwhile */
} /* Endfor */
} /* Endwhile */
timer_component_ptr->ID = id + 1;
return(id);
} /* Endbody */
/*!
* \brief This is the function that is called by a task during task destruction,
* in order to cleanup any timers.
*
* \param[in] td_ptr The task being destroyed.
*/
void _timer_cleanup
(
TD_STRUCT_PTR td_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
QUEUE_STRUCT_PTR queue_ptr;
TIMER_ENTRY_STRUCT_PTR element_ptr;
TIMER_ENTRY_STRUCT_PTR next_element_ptr;
_GET_KERNEL_DATA(kernel_data);
timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
return;
} /* Endif */
/* Gain exclusive access to the timer queues */
_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
queue_ptr = (QUEUE_STRUCT_PTR)&timer_component_ptr->ELAPSED_TIMER_ENTRIES;
element_ptr = (TIMER_ENTRY_STRUCT_PTR)((pointer)queue_ptr->NEXT);
while ((pointer)element_ptr != (pointer)queue_ptr)
{
next_element_ptr = (TIMER_ENTRY_STRUCT_PTR)
((pointer)element_ptr->QUEUE_ELEMENT.NEXT);
if (element_ptr->TD_PTR == td_ptr)
{
_QUEUE_REMOVE(queue_ptr, element_ptr);
element_ptr->VALID = 0;
_mem_free(element_ptr);
} /* Endif */
element_ptr = next_element_ptr;
} /* Endwhile */
queue_ptr = (QUEUE_STRUCT_PTR)
((pointer)&timer_component_ptr->KERNEL_TIMER_ENTRIES);
element_ptr = (TIMER_ENTRY_STRUCT_PTR)((pointer)queue_ptr->NEXT);
while ((pointer)element_ptr != (pointer)queue_ptr)
{
next_element_ptr = (TIMER_ENTRY_STRUCT_PTR)
((pointer)element_ptr->QUEUE_ELEMENT.NEXT);
if (element_ptr->TD_PTR == td_ptr)
{
_QUEUE_REMOVE(queue_ptr, element_ptr);
element_ptr->VALID = 0;
_mem_free(element_ptr);
} /* Endif */
element_ptr = next_element_ptr;
} /* Endwhile */
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
} /* Endbody */
/*!
* \brief Tests the timer component for validity and consistency.
*
* \param[out] timer_error_ptr Pointer to the first timer entry that has an error.
*
* \return MQX_OK
* \return MQX_INVALID_COMPONENT_HANDLE (One of the timer entries in the timer
* queue is not valid (timer_error_ptr).)
* \return MQX_CORRUPT_QUEUE (Queue of timers is not valid.)
*
* \see _timer_start_oneshot_after
* \see _timer_start_oneshot_after_ticks
* \see _timer_start_oneshot_at
* \see _timer_start_oneshot_at_ticks
* \see _timer_start_periodic_at
* \see _timer_start_periodic_at_ticks
* \see _timer_start_periodic_every
* \see _timer_start_periodic_every_ticks
* \see _timer_cancel
*/
_mqx_uint _timer_test
(
pointer _PTR_ timer_error_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TIMER_COMPONENT_STRUCT_PTR timer_component_ptr;
QUEUE_STRUCT_PTR queue_ptr;
TIMER_ENTRY_STRUCT_PTR element_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_timer_test, timer_error_ptr);
*timer_error_ptr = NULL;
timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER];
if (timer_component_ptr == NULL)
{
_KLOGX2(KLOG_timer_test, MQX_OK);
return(MQX_OK);
} /* Endif */
/* Gain exclusive access to the timer queues */
_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
result = _queue_test(&timer_component_ptr->ELAPSED_TIMER_ENTRIES,
timer_error_ptr);
if (result != MQX_OK)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
_KLOGX3(KLOG_timer_test, result, *timer_error_ptr);
return(result);
} /* Endif */
result = _queue_test(&timer_component_ptr->KERNEL_TIMER_ENTRIES,
timer_error_ptr);
if (result != MQX_OK)
{
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
_KLOGX3(KLOG_timer_test, result, *timer_error_ptr);
return(result);
} /* Endif */
queue_ptr = (pointer)&timer_component_ptr->ELAPSED_TIMER_ENTRIES;
element_ptr = (pointer)queue_ptr->NEXT;
while (element_ptr != (pointer)queue_ptr)
{
#if MQX_CHECK_VALIDITY
if (element_ptr->VALID != TIMER_VALID)
{
*timer_error_ptr = element_ptr;
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
_KLOGX3(KLOG_timer_test, MQX_INVALID_COMPONENT_HANDLE,
*timer_error_ptr);
return(MQX_INVALID_COMPONENT_HANDLE);
} /* Endif */
#endif
element_ptr = (pointer)element_ptr->QUEUE_ELEMENT.NEXT;
} /* Endwhile */
queue_ptr = (pointer)&timer_component_ptr->KERNEL_TIMER_ENTRIES;
element_ptr = (pointer)queue_ptr->NEXT;
while (element_ptr != (pointer)queue_ptr)
{
#if MQX_CHECK_VALIDITY
if (element_ptr->VALID != TIMER_VALID)
{
*timer_error_ptr = element_ptr;
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
_KLOGX3(KLOG_timer_test, MQX_INVALID_COMPONENT_HANDLE,
*timer_error_ptr);
return(MQX_INVALID_COMPONENT_HANDLE);
} /* Endif */
#endif
element_ptr = (pointer)element_ptr->QUEUE_ELEMENT.NEXT;
} /* Endwhile */
_lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM);
_KLOGX2(KLOG_timer_test, MQX_OK);
return(MQX_OK);
} /* Endbody */
#endif /* MQX_USE_TIMER */
/* EOF */