567 lines
15 KiB
C
567 lines
15 KiB
C
|
/**************************************************************************************************
|
|||
|
Filename: OSAL_Timers.c
|
|||
|
Revised: $Date: 2010-09-17 16:25:30 -0700 (Fri, 17 Sep 2010) $
|
|||
|
Revision: $Revision: 23835 $
|
|||
|
|
|||
|
Description: OSAL Timer definition and manipulation functions.
|
|||
|
|
|||
|
|
|||
|
Copyright 2004-2009 Texas Instruments Incorporated. All rights reserved.
|
|||
|
|
|||
|
IMPORTANT: Your use of this Software is limited to those specific rights
|
|||
|
granted under the terms of a software license agreement between the user
|
|||
|
who downloaded the software, his/her employer (which must be your employer)
|
|||
|
and Texas Instruments Incorporated (the "License"). You may not use this
|
|||
|
Software unless you agree to abide by the terms of the License. The License
|
|||
|
limits your use, and you acknowledge, that the Software may not be modified,
|
|||
|
copied or distributed unless embedded on a Texas Instruments microcontroller
|
|||
|
or used solely and exclusively in conjunction with a Texas Instruments radio
|
|||
|
frequency transceiver, which is integrated into your product. Other than for
|
|||
|
the foregoing purpose, you may not use, reproduce, copy, prepare derivative
|
|||
|
works of, modify, distribute, perform, display or sell this Software and/or
|
|||
|
its documentation for any purpose.
|
|||
|
|
|||
|
YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE
|
|||
|
PROVIDED <EFBFBD>AS IS<EFBFBD> WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED,
|
|||
|
INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE,
|
|||
|
NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL
|
|||
|
TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT,
|
|||
|
NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER
|
|||
|
LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES
|
|||
|
INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE
|
|||
|
OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT
|
|||
|
OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES
|
|||
|
(INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS.
|
|||
|
|
|||
|
Should you have any questions regarding your right to use this Software,
|
|||
|
contact Texas Instruments Incorporated at www.TI.com.
|
|||
|
**************************************************************************************************/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* INCLUDES
|
|||
|
*/
|
|||
|
|
|||
|
#include "comdef.h"
|
|||
|
#include "OnBoard.h"
|
|||
|
#include "OSAL.h"
|
|||
|
#include "OSAL_Timers.h"
|
|||
|
#include "hal_timer.h"
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* MACROS
|
|||
|
*/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* CONSTANTS
|
|||
|
*/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* TYPEDEFS
|
|||
|
*/
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
void *next;
|
|||
|
uint16 timeout;
|
|||
|
uint16 event_flag;
|
|||
|
uint8 task_id;
|
|||
|
uint16 reloadTimeout;
|
|||
|
} osalTimerRec_t;
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* GLOBAL VARIABLES
|
|||
|
*/
|
|||
|
|
|||
|
osalTimerRec_t *timerHead;
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* EXTERNAL VARIABLES
|
|||
|
*/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* EXTERNAL FUNCTIONS
|
|||
|
*/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* LOCAL VARIABLES
|
|||
|
*/
|
|||
|
// Milliseconds since last reboot
|
|||
|
static uint32 osal_systemClock;
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* LOCAL FUNCTION PROTOTYPES
|
|||
|
*/
|
|||
|
osalTimerRec_t *osalAddTimer( uint8 task_id, uint16 event_flag, uint16 timeout );
|
|||
|
osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag );
|
|||
|
void osalDeleteTimer( osalTimerRec_t *rmTimer );
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* FUNCTIONS
|
|||
|
*********************************************************************/
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osalTimerInit
|
|||
|
*
|
|||
|
* @brief Initialization for the OSAL Timer System.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return
|
|||
|
*/
|
|||
|
void osalTimerInit( void )
|
|||
|
{
|
|||
|
osal_systemClock = 0;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osalAddTimer
|
|||
|
*
|
|||
|
* @brief Add a timer to the timer list.
|
|||
|
* Ints must be disabled.
|
|||
|
*
|
|||
|
* @param task_id
|
|||
|
* @param event_flag
|
|||
|
* @param timeout
|
|||
|
*
|
|||
|
* @return osalTimerRec_t * - pointer to newly created timer
|
|||
|
*/
|
|||
|
osalTimerRec_t * osalAddTimer( uint8 task_id, uint16 event_flag, uint16 timeout )
|
|||
|
{
|
|||
|
osalTimerRec_t *newTimer;
|
|||
|
osalTimerRec_t *srchTimer;
|
|||
|
|
|||
|
// Look for an existing timer first
|
|||
|
newTimer = osalFindTimer( task_id, event_flag );
|
|||
|
if ( newTimer )
|
|||
|
{
|
|||
|
// Timer is found - update it.
|
|||
|
newTimer->timeout = timeout;
|
|||
|
|
|||
|
return ( newTimer );
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// New Timer
|
|||
|
newTimer = osal_mem_alloc( sizeof( osalTimerRec_t ) );
|
|||
|
|
|||
|
if ( newTimer )
|
|||
|
{
|
|||
|
// Fill in new timer
|
|||
|
newTimer->task_id = task_id;
|
|||
|
newTimer->event_flag = event_flag;
|
|||
|
newTimer->timeout = timeout;
|
|||
|
newTimer->next = (void *)NULL;
|
|||
|
newTimer->reloadTimeout = 0;
|
|||
|
|
|||
|
// Does the timer list already exist
|
|||
|
if ( timerHead == NULL )
|
|||
|
{
|
|||
|
// Start task list
|
|||
|
timerHead = newTimer;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Add it to the end of the timer list
|
|||
|
srchTimer = timerHead;
|
|||
|
|
|||
|
// Stop at the last record
|
|||
|
while ( srchTimer->next )
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
|
|||
|
// Add to the list
|
|||
|
srchTimer->next = newTimer;
|
|||
|
}
|
|||
|
|
|||
|
return ( newTimer );
|
|||
|
}
|
|||
|
else
|
|||
|
return ( (osalTimerRec_t *)NULL );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osalFindTimer
|
|||
|
*
|
|||
|
* @brief Find a timer in a timer list.
|
|||
|
* Ints must be disabled.
|
|||
|
*
|
|||
|
* @param task_id
|
|||
|
* @param event_flag
|
|||
|
*
|
|||
|
* @return osalTimerRec_t *
|
|||
|
*/
|
|||
|
osalTimerRec_t *osalFindTimer( uint8 task_id, uint16 event_flag )
|
|||
|
{
|
|||
|
osalTimerRec_t *srchTimer;
|
|||
|
|
|||
|
// Head of the timer list
|
|||
|
srchTimer = timerHead;
|
|||
|
|
|||
|
// Stop when found or at the end
|
|||
|
while ( srchTimer )
|
|||
|
{
|
|||
|
if ( srchTimer->event_flag == event_flag &&
|
|||
|
srchTimer->task_id == task_id )
|
|||
|
break;
|
|||
|
|
|||
|
// Not this one, check another
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
}
|
|||
|
|
|||
|
return ( srchTimer );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osalDeleteTimer
|
|||
|
*
|
|||
|
* @brief Delete a timer from a timer list.
|
|||
|
*
|
|||
|
* @param table
|
|||
|
* @param rmTimer
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*/
|
|||
|
void osalDeleteTimer( osalTimerRec_t *rmTimer )
|
|||
|
{
|
|||
|
// Does the timer list really exist
|
|||
|
if ( rmTimer )
|
|||
|
{
|
|||
|
// Clear the event flag and osalTimerUpdate() will delete
|
|||
|
// the timer from the list.
|
|||
|
rmTimer->event_flag = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_start_timerEx
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* This function is called to start a timer to expire in n mSecs.
|
|||
|
* When the timer expires, the calling task will get the specified event.
|
|||
|
*
|
|||
|
* @param uint8 taskID - task id to set timer for
|
|||
|
* @param uint16 event_id - event to be notified with
|
|||
|
* @param UNINT16 timeout_value - in milliseconds.
|
|||
|
*
|
|||
|
* @return SUCCESS, or NO_TIMER_AVAIL.
|
|||
|
*/
|
|||
|
uint8 osal_start_timerEx( uint8 taskID, uint16 event_id, uint16 timeout_value )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
osalTimerRec_t *newTimer;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
// Add timer
|
|||
|
newTimer = osalAddTimer( taskID, event_id, timeout_value );
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_start_reload_timer
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* This function is called to start a timer to expire in n mSecs.
|
|||
|
* When the timer expires, the calling task will get the specified event
|
|||
|
* and the timer will be reloaded with the timeout value.
|
|||
|
*
|
|||
|
* @param uint8 taskID - task id to set timer for
|
|||
|
* @param uint16 event_id - event to be notified with
|
|||
|
* @param UNINT16 timeout_value - in milliseconds.
|
|||
|
*
|
|||
|
* @return SUCCESS, or NO_TIMER_AVAIL.
|
|||
|
*/
|
|||
|
uint8 osal_start_reload_timer( uint8 taskID, uint16 event_id, uint16 timeout_value )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
osalTimerRec_t *newTimer;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
// Add timer
|
|||
|
newTimer = osalAddTimer( taskID, event_id, timeout_value );
|
|||
|
if ( newTimer )
|
|||
|
{
|
|||
|
// Load the reload timeout value
|
|||
|
newTimer->reloadTimeout = timeout_value;
|
|||
|
}
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
return ( (newTimer != NULL) ? SUCCESS : NO_TIMER_AVAIL );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_stop_timerEx
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* This function is called to stop a timer that has already been started.
|
|||
|
* If ZSUCCESS, the function will cancel the timer and prevent the event
|
|||
|
* associated with the timer from being set for the calling task.
|
|||
|
*
|
|||
|
* @param uint8 task_id - task id of timer to stop
|
|||
|
* @param uint16 event_id - identifier of the timer that is to be stopped
|
|||
|
*
|
|||
|
* @return SUCCESS or INVALID_EVENT_ID
|
|||
|
*/
|
|||
|
uint8 osal_stop_timerEx( uint8 task_id, uint16 event_id )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
osalTimerRec_t *foundTimer;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
// Find the timer to stop
|
|||
|
foundTimer = osalFindTimer( task_id, event_id );
|
|||
|
if ( foundTimer )
|
|||
|
{
|
|||
|
osalDeleteTimer( foundTimer );
|
|||
|
}
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
return ( (foundTimer != NULL) ? SUCCESS : INVALID_EVENT_ID );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_get_timeoutEx
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* @param uint8 task_id - task id of timer to check
|
|||
|
* @param uint16 event_id - identifier of timer to be checked
|
|||
|
*
|
|||
|
* @return Return the timer's tick count if found, zero otherwise.
|
|||
|
*/
|
|||
|
uint16 osal_get_timeoutEx( uint8 task_id, uint16 event_id )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
uint16 rtrn = 0;
|
|||
|
osalTimerRec_t *tmr;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
tmr = osalFindTimer( task_id, event_id );
|
|||
|
|
|||
|
if ( tmr )
|
|||
|
{
|
|||
|
rtrn = tmr->timeout;
|
|||
|
}
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
return rtrn;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_timer_num_active
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* This function counts the number of active timers.
|
|||
|
*
|
|||
|
* @return uint8 - number of timers
|
|||
|
*/
|
|||
|
uint8 osal_timer_num_active( void )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
uint8 num_timers = 0;
|
|||
|
osalTimerRec_t *srchTimer;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
// Head of the timer list
|
|||
|
srchTimer = timerHead;
|
|||
|
|
|||
|
// Count timers in the list
|
|||
|
while ( srchTimer != NULL )
|
|||
|
{
|
|||
|
num_timers++;
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
}
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
return num_timers;
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osalTimerUpdate
|
|||
|
*
|
|||
|
* @brief Update the timer structures for a timer tick.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*********************************************************************/
|
|||
|
void osalTimerUpdate( uint16 updateTime )
|
|||
|
{
|
|||
|
halIntState_t intState;
|
|||
|
osalTimerRec_t *srchTimer;
|
|||
|
osalTimerRec_t *prevTimer;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
// Update the system time
|
|||
|
osal_systemClock += updateTime;
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
// Look for open timer slot
|
|||
|
if ( timerHead != NULL )
|
|||
|
{
|
|||
|
// Add it to the end of the timer list
|
|||
|
srchTimer = timerHead;
|
|||
|
prevTimer = (void *)NULL;
|
|||
|
|
|||
|
// Look for open timer slot
|
|||
|
while ( srchTimer )
|
|||
|
{
|
|||
|
osalTimerRec_t *freeTimer = NULL;
|
|||
|
|
|||
|
HAL_ENTER_CRITICAL_SECTION( intState ); // Hold off interrupts.
|
|||
|
|
|||
|
if (srchTimer->timeout <= updateTime)
|
|||
|
{
|
|||
|
srchTimer->timeout = 0;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
srchTimer->timeout = srchTimer->timeout - updateTime;
|
|||
|
}
|
|||
|
|
|||
|
// Check for reloading
|
|||
|
if ( (srchTimer->timeout == 0) && (srchTimer->reloadTimeout) && (srchTimer->event_flag) )
|
|||
|
{
|
|||
|
// Notify the task of a timeout
|
|||
|
osal_set_event( srchTimer->task_id, srchTimer->event_flag );
|
|||
|
|
|||
|
// Reload the timer timeout value
|
|||
|
srchTimer->timeout = srchTimer->reloadTimeout;
|
|||
|
}
|
|||
|
|
|||
|
// When timeout or delete (event_flag == 0)
|
|||
|
if ( srchTimer->timeout == 0 || srchTimer->event_flag == 0 )
|
|||
|
{
|
|||
|
// Take out of list
|
|||
|
if ( prevTimer == NULL )
|
|||
|
timerHead = srchTimer->next;
|
|||
|
else
|
|||
|
prevTimer->next = srchTimer->next;
|
|||
|
|
|||
|
// Setup to free memory
|
|||
|
freeTimer = srchTimer;
|
|||
|
|
|||
|
// Next
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// Get next
|
|||
|
prevTimer = srchTimer;
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
}
|
|||
|
|
|||
|
HAL_EXIT_CRITICAL_SECTION( intState ); // Re-enable interrupts.
|
|||
|
|
|||
|
if ( freeTimer )
|
|||
|
{
|
|||
|
if ( freeTimer->timeout == 0 )
|
|||
|
{
|
|||
|
osal_set_event( freeTimer->task_id, freeTimer->event_flag );
|
|||
|
}
|
|||
|
osal_mem_free( freeTimer );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#ifdef POWER_SAVING
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_adjust_timers
|
|||
|
*
|
|||
|
* @brief Update the timer structures for elapsed ticks.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*********************************************************************/
|
|||
|
void osal_adjust_timers( void )
|
|||
|
{
|
|||
|
uint16 eTime;
|
|||
|
|
|||
|
if ( timerHead != NULL )
|
|||
|
{
|
|||
|
// Compute elapsed time (msec)
|
|||
|
eTime = TimerElapsed() / TICK_COUNT;
|
|||
|
|
|||
|
if ( eTime )
|
|||
|
osalTimerUpdate( eTime );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_next_timeout
|
|||
|
*
|
|||
|
* @brief
|
|||
|
*
|
|||
|
* Search timer table to return the lowest timeout value. If the
|
|||
|
* timer list is empty, then the returned timeout will be zero.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return none
|
|||
|
*********************************************************************/
|
|||
|
uint16 osal_next_timeout( void )
|
|||
|
{
|
|||
|
uint16 nextTimeout;
|
|||
|
osalTimerRec_t *srchTimer;
|
|||
|
|
|||
|
if ( timerHead != NULL )
|
|||
|
{
|
|||
|
// Head of the timer list
|
|||
|
srchTimer = timerHead;
|
|||
|
nextTimeout = OSAL_TIMERS_MAX_TIMEOUT;
|
|||
|
|
|||
|
// Look for the next timeout timer
|
|||
|
while ( srchTimer != NULL )
|
|||
|
{
|
|||
|
if (srchTimer->timeout < nextTimeout)
|
|||
|
{
|
|||
|
nextTimeout = srchTimer->timeout;
|
|||
|
}
|
|||
|
// Check next timer
|
|||
|
srchTimer = srchTimer->next;
|
|||
|
}
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
// No timers
|
|||
|
nextTimeout = 0;
|
|||
|
}
|
|||
|
|
|||
|
return ( nextTimeout );
|
|||
|
}
|
|||
|
#endif // POWER_SAVING
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
* @fn osal_GetSystemClock()
|
|||
|
*
|
|||
|
* @brief Read the local system clock.
|
|||
|
*
|
|||
|
* @param none
|
|||
|
*
|
|||
|
* @return local clock in milliseconds
|
|||
|
*/
|
|||
|
uint32 osal_GetSystemClock( void )
|
|||
|
{
|
|||
|
return ( osal_systemClock );
|
|||
|
}
|
|||
|
|
|||
|
/*********************************************************************
|
|||
|
*********************************************************************/
|