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

413 lines
12 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: lwtimer.c$
* $Version : 3.8.5.1$
* $Date : Feb-20-2012$
*
* Comments:
*
* This file contains functions of the LWTimer component.
*
*END************************************************************************/
#include "mqx_inc.h"
#if MQX_USE_LWTIMER
#include "lwtimer.h"
#include "lwtimer_prv.h"
/*!
* \brief Creates the periodic timer queue.
*
* \param[in] period_ptr The location of the data structure to be initialized.
* \param[in] period The cycle length of this timer in ticks.
* \param[in] wait_ticks The number of ticks to wait before starting this queue.
*
* \return MQX_OK
*
* \see _lwtimer_add_timer_to_queue
* \see _lwtimer_cancel_period
* \see _lwtimer_cancel_timer
* \see _lwtimer_create_periodic_queue
* \see LWTIMER_PERIOD_STRUCT
*/
_mqx_uint _lwtimer_create_periodic_queue
(
LWTIMER_PERIOD_STRUCT_PTR period_ptr,
_mqx_uint period,
_mqx_uint wait_ticks
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
_GET_KERNEL_DATA(kernel_data);
_KLOGE4(KLOG_lwtimer_create_periodic_queue, period_ptr, period, wait_ticks);
period_ptr->PERIOD = period;
period_ptr->EXPIRY = 0;
period_ptr->WAIT = wait_ticks;
_QUEUE_INIT(&period_ptr->TIMERS,0);
period_ptr->TIMER_PTR = (pointer) &period_ptr->TIMERS;
_int_disable();
if (kernel_data->LWTIMERS.NEXT == NULL)
{
/* Initialize the light weight timer queue */
_QUEUE_INIT(&kernel_data->LWTIMERS, 0);
kernel_data->LWTIMER_ISR = _lwtimer_isr_internal;
} /* Endif */
period_ptr->VALID = LWTIMER_VALID;
_QUEUE_ENQUEUE(&kernel_data->LWTIMERS, &period_ptr->LINK);
_int_enable();
_KLOGX2(KLOG_lwtimer_create_periodic_queue, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Adds the lightweight timer to the periodic queue.
*
* This function inserts the timer in the queue in order of increasing offset
* from the queue's start time.
*
* \param[in] period_ptr Pointer to the periodic queue.
* \param[in] timer_ptr Pointer to the lightweight timer to add to the queue,
* must be smaller than queue.
* \param[in] ticks Tick offset from the timers period to expire at.
* \param[in] func Function to call when the timer expires.
* \param[in] parameter Parameter to pass to the function.
*
* \return MQX_OK
* \return MQX_LWTIMER_INVALID (Period_ptr points to an invalid periodic queue.)
* \return MQX_INVALID_PARAMETER (Ticks is greater than or equal to the
* periodic queue's period.)
*
* \see _lwtimer_cancel_period
* \see _lwtimer_cancel_timer
* \see _lwtimer_create_periodic_queue
* \see LWTIMER_PERIOD_STRUCT
* \see LWTIMER_STRUCT
*/
_mqx_uint _lwtimer_add_timer_to_queue
(
LWTIMER_PERIOD_STRUCT_PTR period_ptr,
LWTIMER_STRUCT_PTR timer_ptr,
_mqx_uint ticks,
LWTIMER_ISR_FPTR func,
pointer parameter
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
LWTIMER_STRUCT_PTR qe_ptr;
_mqx_uint i;
_GET_KERNEL_DATA(kernel_data);
_KLOGE4(KLOG_lwtimer_add_timer_to_queue, period_ptr, timer_ptr, ticks);
#if MQX_CHECK_ERRORS
if (period_ptr->VALID != LWTIMER_VALID)
{
_KLOGX2(KLOG_lwtimer_add_timer_to_queue, MQX_LWTIMER_INVALID);
return (MQX_LWTIMER_INVALID);
} /* Endif */
if (ticks >= period_ptr->PERIOD)
{
_KLOGX2(KLOG_lwtimer_add_timer_to_queue, MQX_INVALID_PARAMETER);
return (MQX_INVALID_PARAMETER);
} /* Endif */
#endif
timer_ptr->TIMER_FUNCTION = func;
timer_ptr->PARAMETER = parameter;
timer_ptr->PERIOD_PTR = period_ptr;
timer_ptr->RELATIVE_TICKS = ticks;
_int_disable();
/* Insert into queue in order of increasing offset from start time */
qe_ptr = (pointer) &period_ptr->TIMERS.NEXT;
i = _QUEUE_GET_SIZE(&period_ptr->TIMERS) + 1;
while (--i)
{
qe_ptr = (pointer) qe_ptr->LINK.NEXT;
if (qe_ptr->RELATIVE_TICKS >= ticks)
{
qe_ptr = (pointer) qe_ptr->LINK.PREV;
break;
} /* Endif */
} /* Endwhile */
timer_ptr->VALID = LWTIMER_VALID;
_QUEUE_INSERT(&period_ptr->TIMERS, qe_ptr, &timer_ptr->LINK);
_int_enable();
_KLOGX2(KLOG_lwtimer_add_timer_to_queue, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \private
*
* \brief This function checks the lwtimer queues, and if a timer is ready,
* calls an application function.
*/
void _lwtimer_isr_internal(void)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
LWTIMER_PERIOD_STRUCT_PTR period_ptr;
LWTIMER_STRUCT_PTR timer_ptr;
_GET_KERNEL_DATA(kernel_data);
period_ptr = (pointer) kernel_data->LWTIMERS.NEXT;
while ((pointer) period_ptr != (pointer) &kernel_data->LWTIMERS)
{
if (period_ptr->WAIT)
{
--period_ptr->WAIT;
}
else
{
timer_ptr = (pointer) period_ptr->TIMER_PTR->LINK.NEXT;
for (; timer_ptr != (pointer) &period_ptr->TIMERS; timer_ptr = (LWTIMER_STRUCT_PTR) (pointer) timer_ptr->LINK.NEXT)
{
if (timer_ptr->RELATIVE_TICKS > period_ptr->EXPIRY)
{
break;
} /* Endif */
/* Save the last timer processed */
period_ptr->TIMER_PTR = timer_ptr;
(*timer_ptr->TIMER_FUNCTION)(timer_ptr->PARAMETER);
} /* Endwhile */
if (++period_ptr->EXPIRY == period_ptr->PERIOD)
{
period_ptr->EXPIRY = 0;
period_ptr->TIMER_PTR = (pointer) &period_ptr->TIMERS;
} /* Endif */
} /* Endif */
period_ptr = (LWTIMER_PERIOD_STRUCT_PTR) (pointer) period_ptr->LINK.NEXT;
} /* Endwhile */
} /* Endbody */
/*!
* \brief Cancels an outstanding timer request.
*
* \param[in] timer_ptr Pointer to the lightweight timer to cancel.
*
* \return MQX_OK
* \return MQX_LWTIMER_INVALID (Timer_ptr points to either an invalid timer or
* to a timer with a periodic queue.)
*
* \see _lwtimer_add_timer_to_queue
* \see _lwtimer_cancel_period
* \see _lwtimer_create_periodic_queue
* \see LWTIMER_STRUCT
*/
_mqx_uint _lwtimer_cancel_timer
(
LWTIMER_STRUCT_PTR timer_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
LWTIMER_PERIOD_STRUCT_PTR period_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_lwtimer_cancel_timer, timer_ptr);
#if MQX_CHECK_VALIDITY
if (timer_ptr->VALID != LWTIMER_VALID)
{
_KLOGX2(KLOG_lwtimer_cancel_timer, MQX_LWTIMER_INVALID);
return MQX_LWTIMER_INVALID;
} /* Endif */
#endif
period_ptr = timer_ptr->PERIOD_PTR;
_int_disable();
#if MQX_CHECK_VALIDITY
if (period_ptr->VALID != LWTIMER_VALID)
{
_int_enable();
_KLOGX2(KLOG_lwtimer_cancel_timer, MQX_LWTIMER_INVALID);
return MQX_LWTIMER_INVALID;
} /* Endif */
#endif
timer_ptr->VALID = 0;
if (timer_ptr == period_ptr->TIMER_PTR)
{
period_ptr->TIMER_PTR = (pointer) timer_ptr->LINK.PREV;
} /* Endif */
_QUEUE_REMOVE(&period_ptr->TIMERS, timer_ptr);
_int_enable();
_KLOGX2(KLOG_lwtimer_cancel_timer, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Cancels all the lightweight timers in the periodic queue.
*
* \param[in] period_ptr Pointer to the periodic queue to cancel.
*
* \return MQX_OK
* \return MQX_LWTIMER_INVALID (Period_ptr points to an invalid periodic queue.)
*
* \see _lwtimer_add_timer_to_queue
* \see _lwtimer_cancel_timer
* \see _lwtimer_create_periodic_queue
* \see LWTIMER_PERIOD_STRUCT
*/
_mqx_uint _lwtimer_cancel_period
(
LWTIMER_PERIOD_STRUCT_PTR period_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_lwtimer_cancel_period, period_ptr);
#if MQX_CHECK_VALIDITY
if (period_ptr->VALID != LWTIMER_VALID)
{
_KLOGX2(KLOG_lwtimer_cancel_period, MQX_LWTIMER_INVALID);
return MQX_LWTIMER_INVALID;
} /* Endif */
#endif
_int_disable();
period_ptr->VALID = 0;
_QUEUE_REMOVE(&kernel_data->LWTIMERS, period_ptr);
_int_enable();
_KLOGX2(KLOG_lwtimer_cancel_period, MQX_OK);
return (MQX_OK);
} /* Endbody */
/*!
* \brief Tests all the periodic queues and their lightweight timers for
* validity and consistency.
*
* \param[out] period_error_ptr Pointer to the first periodic queue that has
* an error (NULL if no error is found).
* \param[out] timer_error_ptr Pointer to the first timer that has an error
* (NULL if no error is found).
*
* \return MQX_OK (No periodic queues have been created or no errors found
* in any periodic queues or timers.)
* \return MQX_LWTIMER_INVALID (Period_ptr points to an invalid periodic queue.)
* \return Error from _queue_test() (A periodic queue or its queue was in error.)
*
* \see _lwtimer_add_timer_to_queue
* \see _lwtimer_cancel_period
* \see _lwtimer_cancel_timer
* \see _lwtimer_create_periodic_queue
*/
_mqx_uint _lwtimer_test
(
pointer _PTR_ period_error_ptr,
pointer _PTR_ timer_error_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
LWTIMER_STRUCT_PTR timer_ptr;
LWTIMER_PERIOD_STRUCT_PTR period_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_lwtimer_test, period_error_ptr, timer_error_ptr);
*period_error_ptr = NULL;
*timer_error_ptr = NULL;
/*
* It is not considered an error if the lwtimer component has not been
* created yet
*/
if (kernel_data->LWTIMERS.NEXT == NULL)
{
return (MQX_OK);
} /* Endif */
result = _queue_test(&kernel_data->LWTIMERS, period_error_ptr);
if (result != MQX_OK)
{
_KLOGX3(KLOG_lwtimer_test, result, *period_error_ptr);
return (result);
} /* Endif */
_int_disable();
period_ptr = (pointer) kernel_data->LWTIMERS.NEXT;
while ((pointer) period_ptr != (pointer) &kernel_data->LWTIMERS)
{
if (period_ptr->VALID != LWTIMER_VALID)
{
_int_enable();
*period_error_ptr = period_ptr;
_KLOGX3(KLOG_lwtimer_test, MQX_LWTIMER_INVALID, period_ptr);
return (MQX_LWTIMER_INVALID);
} /* Endif */
result = _queue_test(&period_ptr->TIMERS, timer_error_ptr);
if (result != MQX_OK)
{
_int_enable();
*period_error_ptr = period_ptr;
_KLOGX4(KLOG_lwtimer_test, result, *period_error_ptr, *timer_error_ptr);
return (result);
} /* Endif */
timer_ptr = (pointer) period_ptr->TIMERS.NEXT;
while (timer_ptr != (pointer) &period_ptr->TIMERS)
{
if (timer_ptr->VALID != LWTIMER_VALID)
{
*period_error_ptr = period_ptr;
*timer_error_ptr = timer_ptr;
_KLOGX4(KLOG_lwtimer_test, MQX_LWTIMER_INVALID, period_ptr,
timer_ptr);
return (MQX_LWTIMER_INVALID);
} /* Endif */
timer_ptr = (pointer) timer_ptr->LINK.NEXT;
} /* Endwhile */
period_ptr = (pointer) period_ptr->LINK.NEXT;
} /* Endwhile */
_int_enable();
_KLOGX2(KLOG_lwtimer_test, MQX_OK);
return (MQX_OK);
} /* Endbody */
#endif /* MQX_USE_LWTIMER */
/* EOF */