您的位置:首页 > 其它

OSAL事件触发机制----定时器触发

2015-11-18 15:38 357 查看
OSAL事件触发机制----定时器触发

OSAL系统进入主循环后,轮询任务事件标志tasksEvents[],发现存在任务及其事件则进入tasksArr[]调用相对应的回调函数进行任务事件的处理,轮询任务前,向

1、由定时器超时溢出,设置任务及事件;

2、由外部信号(如按键)触发消息传递机制,设置任务及事件;

3、可调用osal_set_event()函数进行设定。

/*********************************************************************

* @fn      osal_set_event

* @brief

*    This function is called to set the event flags for a task. The

*    event passed in is OR'd into the task's event variable.

* @param   uint8 task_id - receiving tasks ID

* @param   uint8 event_flag - what event to set

* @return  SUCCESS, INVALID_TASK

*/

uint8 osal_set_event( uint8 task_id, uint16 event_flag )

{

if ( task_id < tasksCnt )

{

halIntState_t   intState;

HAL_ENTER_CRITICAL_SECTION(intState);    // Hold off interrupts

tasksEvents[task_id] |= event_flag;  // Stuff the event bit(s)

HAL_EXIT_CRITICAL_SECTION(intState);     // Release interrupts

return ( SUCCESS );

}

else

{

return ( INVALID_TASK );

}

}


OSAL中,由osal_set_event()向主循环注入事件等待处理,

tasksEvents[task_id] |= event_flag;

task_id为任务ID,event_flag为该任务待处理事件。

不论是定时器还是消息传递,最终注入事件都是调用osal_set_event()完成。

1、 定时器触发事件流程

调用osal_start_timerEx()函数创建定时任务,该函数中调用osalAddTimer()接口,添加定时器函数中,遍历定时器链表,若存在该任务ID同事件的定时器,更新定时器超时时间,若不存在,则创建一个新定时器,将新创建的定时器添加到定时器链表中并返回定时器指针,创建失败返回NULL。

OSAL调用osalTimeUpdate()函数进行定时器遍历,

/*********************************************************************

* @fn      osalTimeUpdate

*

* @brief    Uses the free running rollover count of the MAC backoff timer;

*          this timer runs freely with a constant 320 usec interval.  The

*          count of 320-usec ticks is converted to msecs and used to update

*          the OSAL clock and Timers by invoking osalClockUpdate() and

*          osalTimerUpdate().  This function is intended to be invoked

*          from the background, not interrupt level.

*

* @param   None.

*

* @return  None.

*/

void osalTimeUpdate( void )

{

uint16 tmp;

uint16 ticks625us;

uint16 elapsedMSec = 0;

// Get the free-running count of 625us timer ticks

tmp = ll_McuPrecisionCount();

if ( tmp != previousLLTimerTick )

{

// Calculate the elapsed ticks of the free-running timer.

ticks625us = tmp - previousLLTimerTick;

// Store the LL Timer tick count for the next time through this function.

previousLLTimerTick = tmp;

/* It is necessary to loop to convert the usecs to msecs in increments so as

* not to overflow the 16-bit variables.

*/

while ( ticks625us > MAXCALCTICKS )

{

ticks625us -= MAXCALCTICKS;

elapsedMSec += MAXCALCTICKS * 5 / 8;

remUsTicks += MAXCALCTICKS * 5 % 8;

}

// update converted number with remaining ticks from loop and the

// accumulated remainder from loop

tmp = (ticks625us * 5) + remUsTicks;

// Convert the 625 us ticks into milliseconds and a remainder

elapsedMSec += tmp / 8;

remUsTicks = tmp % 8;

// Update OSAL Clock and Timers

if ( elapsedMSec )

{

osalClockUpdate( elapsedMSec );

osalTimerUpdate( elapsedMSec );

}

}

}


该函数在主循环中调用,使用一个链路层的定时器,根据TI网站上工作人员的回答,使用timer2计时,时间间隔为625us,而不是注释中的320us,该函数中获取到ticks之后,转换为毫秒时间并调用osalClockUpdate()更新系统时间,单位 S;调用osalTimerUpdate()遍历定时器链表。

/*********************************************************************

* @fn      osalTimerUpdate

*

* @brief   Update the timer structures for a timer tick.

*

* @param   none

*

* @return  none

*********************************************************************/

void osalTimerUpdate( uint32 updateTime )

{

halIntState_t intState;

osalTimerRec_t *srchTimer;

osalTimerRec_t *prevTimer;

osalTime_t timeUnion;

timeUnion.time32 = updateTime;

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.

// To minimize time in this critical section, avoid 32-bit math

if ((timeUnion.time16[1] == 0) && (timeUnion.time8[1] == 0))

{

// If upper 24 bits are zero, check lower 8 bits for roll over

if (srchTimer->timeout.time8[0] >= timeUnion.time8[0])

{

// 8-bit math

srchTimer->timeout.time8[0] -= timeUnion.time8[0];

}

else

{

// 32-bit math

if (srchTimer->timeout.time32 > timeUnion.time32)

{

srchTimer->timeout.time32 -= timeUnion.time32;

}

else

{

srchTimer->timeout.time32 = 0;

}

}

}

else

{

// 32-bit math

if (srchTimer->timeout.time32 > timeUnion.time32)

{

srchTimer->timeout.time32 -= timeUnion.time32;

}

else

{

srchTimer->timeout.time32 = 0;

}

}

// Check for reloading

if ( (srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 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.time32 = srchTimer->reloadTimeout;

}

// When timeout or delete (event_flag == 0)

if ( ((srchTimer->timeout.time16[0] == 0) && (srchTimer->timeout.time16[1] == 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.time16[0] == 0) && (freeTimer->timeout.time16[1] == 0) )

{

osal_set_event( freeTimer->task_id, freeTimer->event_flag );

}

osal_mem_free( freeTimer );

}

}

}

}


该函数中获取到系统流逝时间后,存储在一个长度为32位的联合体中timeUnion,并更新系统时钟,单位ms,遍历定时器链表。

a、为了减少时间消耗,没有直接使用32位进行比较,其实本质上还是定时器超时时间减去系统流逝时间,若超时时间小于系统流逝时间,则直接置0;

b、判断是否为循环定时器超时时间为0,是,则调用osal_set_event()向主循环注入任务事件,并reloadTimeout;

c、判断是否是普通定时器超时,是,则调用osal_set_event()向主循环注入任务事件,并删除定时器释放内存。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: