OSAL事件触发机制----定时器触发
2015-11-18 15:38
357 查看
OSAL事件触发机制----定时器触发
OSAL系统进入主循环后,轮询任务事件标志tasksEvents[],发现存在任务及其事件则进入tasksArr[]调用相对应的回调函数进行任务事件的处理,轮询任务前,向
1、由定时器超时溢出,设置任务及事件;
2、由外部信号(如按键)触发消息传递机制,设置任务及事件;
3、可调用osal_set_event()函数进行设定。
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()函数进行定时器遍历,
该函数在主循环中调用,使用一个链路层的定时器,根据TI网站上工作人员的回答,使用timer2计时,时间间隔为625us,而不是注释中的320us,该函数中获取到ticks之后,转换为毫秒时间并调用osalClockUpdate()更新系统时间,单位 S;调用osalTimerUpdate()遍历定时器链表。
该函数中获取到系统流逝时间后,存储在一个长度为32位的联合体中timeUnion,并更新系统时钟,单位ms,遍历定时器链表。
a、为了减少时间消耗,没有直接使用32位进行比较,其实本质上还是定时器超时时间减去系统流逝时间,若超时时间小于系统流逝时间,则直接置0;
b、判断是否为循环定时器超时时间为0,是,则调用osal_set_event()向主循环注入任务事件,并reloadTimeout;
c、判断是否是普通定时器超时,是,则调用osal_set_event()向主循环注入任务事件,并删除定时器释放内存。
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()向主循环注入任务事件,并删除定时器释放内存。
相关文章推荐
- Patial修饰符
- Java判断输入的String是否为中文方法总结
- jq 关于height
- Java内功提升之变量与常量
- Learning Links
- Mac iOS RSA 私钥和公钥的生成
- JavaEE_JavaScript__前台(Jsp页面) + 后台数据处理(Servlet),与javaScript的过程的处理
- Exchange2013 使用EMS命令关联现有的AD组
- unbutu安装nodejs环境
- 前台session判空良策!
- C++拷贝构造函数详解
- 异常介绍、自定义异常、异常面试题
- Qt的进度条设置
- SQL查询到的数据放到DataSet中
- 饭卡---hdu2546(01背包)
- saltstack数据系统之Pillar
- iOS URL编码(全编):
- Swift之mark 注释
- iOS float类型不精确
- 实例详解Linxu中df命令