整理rtthread 的定时器管理源码分析.docx
- 文档编号:27131631
- 上传时间:2023-06-27
- 格式:DOCX
- 页数:45
- 大小:44.08KB
整理rtthread 的定时器管理源码分析.docx
《整理rtthread 的定时器管理源码分析.docx》由会员分享,可在线阅读,更多相关《整理rtthread 的定时器管理源码分析.docx(45页珍藏版)》请在冰豆网上搜索。
整理rtthread的定时器管理源码分析
1前言
rt-thread可以采用软件定时器或硬件定时器来实现定时器管理的,所谓软件定时器是指由操作系统提供的一类系统接口,它构建在硬件定时器基础之上,使系统能够提供不受数目限制的定时器服务。
而硬件定时器是芯片本身提供的定时功能。
一般是由外部晶振提供给芯片输入时钟,芯片向软件模块提供一组配置寄存器,接受控制输入,到达设定时间值后芯片中断控制器产生时钟中断。
硬件定时器的精度一般很高,可以达到纳秒级别,并且是中断触发方式。
软件定时器的精度取决于它使用的硬件定时器精度。
而rt-thread操作系统在默认情况下是采用的硬件定时器的方式,用户可以通过修改宏定义#ifdefRT_USING_TIMER_SOFT来修改采用哪种。
2rt-thread的定时器的基本工作原理
在RT-Thread定时器模块维护两个重要的全局变量,一个是当前系统的时间rt_tick(当硬件定时器中断来临时,它将加1),另一个是定时器链表rt_timer_list,系统中新创建的定时期都会被以排序的方式插入到rt_timer_list(硬件定时器模式下使用)链表中,rt_timer_list的每个节点保留了一个定时器的信息,并且在这个节点加入链表时就计算好了产生时间到达时的时间点,即tick,在rt-thread系统中如果采用软件定时器模式,则存在一定时器线程rt_thread_timer_entry,不断获取当前TICK值并与定时器链表rt_timer_list上的定时器对比判断是否时间已到,一旦发现就调用对应的回调函数,即事件处理函数进行处理,而如果采用硬件定时器管理模式的话,则该检查过程放到系统时钟中断例程中进行处理,此时,是不存在定时器线程的。
如下图:
注:
如果采用软件定时器软件定时器,则该定时器链表为rt_soft_timer_list。
3源码分析
3.1数据定义
[cpp]viewplaincopyprint?
1./**
2. * timer structure
3. */
4.struct rt_timer
5.{
6. struct rt_object parent; //内核对象
7.
8. rt_list_t list; //链表节点
9.
10. void (*timeout_func)(void *parameter); //定时器超时例程
11. void *parameter; //定时器例程的传入参数
12.
13. rt_tick_t init_tick; //定时器的超时时间,即总共多长时间将产生超时事件
14. rt_tick_t timeout_tick; //定时器超时的时间点,即产生超时事件时那一该的时间点
15.};
16.typedef struct rt_timer *rt_timer_t;
/**
*timerstructure
*/
structrt_timer
{
structrt_objectparent;//内核对象
rt_list_tlist;//链表节点
void(*timeout_func)(void*parameter);//定时器超时例程
void*parameter;//定时器例程的传入参数
rt_tick_tinit_tick;//定时器的超时时间,即总共多长时间将产生超时事件
rt_tick_ttimeout_tick;//定时器超时的时间点,即产生超时事件时那一该的时间点
};
typedefstructrt_timer*rt_timer_t;
3.2rt-thread的软件定时器模式
软件定时器线程初始化及启动:
[cpp]viewplaincopyprint?
1./**
2. * @ingroup SystemInit
3. *
4. * This function will initialize system timer thread
5. */
6.void rt_system_timer_thread_init(void)
7.{
8.#ifdef RT_USING_TIMER_SOFT//如果采用软件定时器管理模式,则启动定时器线程
9. rt_list_init(&rt_soft_timer_list);//初始化软件定时器链表
10.
11. /* start software timer thread */
12. rt_thread_init(&timer_thread,//初始化软件定时器线程,并启动
13. "timer",
14. rt_thread_timer_entry,
15. RT_NULL,
16. &timer_thread_stack[0],
17. sizeof(timer_thread_stack),
18. RT_TIMER_THREAD_PRIO,
19. 10);
20.
21. /* startup */
22. rt_thread_startup(&timer_thread);
23.#endif
24.}
/**
*@ingroupSystemInit
*
*Thisfunctionwillinitializesystemtimerthread
*/
voidrt_system_timer_thread_init(void)
{
#ifdefRT_USING_TIMER_SOFT//如果采用软件定时器管理模式,则启动定时器线程
rt_list_init(&rt_soft_timer_list);//初始化软件定时器链表
/*startsoftwaretimerthread*/
rt_thread_init(&timer_thread,//初始化软件定时器线程,并启动
"timer",
rt_thread_timer_entry,
RT_NULL,
&timer_thread_stack[0],
sizeof(timer_thread_stack),
RT_TIMER_THREAD_PRIO,
10);
/*startup*/
rt_thread_startup(&timer_thread);
#endif
}
软件定时器线程如下:
[cpp]viewplaincopyprint?
1./* system timer thread entry */
2.static void rt_thread_timer_entry(void *parameter)
3.{
4. rt_tick_t next_timeout;
5.
6. while
(1)
7. {
8. /* get the next timeout tick */
9. next_timeout = rt_timer_list_next_timeout(&rt_soft_timer_list);//得到软件定时器链表上的下一个定时器的超时时间点
10. if (next_timeout == RT_TICK_MAX)//如果超过范围,则挂起当前线程,继续线程调度
11. {
12. /* no software timer exist, suspend self. */
13. rt_thread_suspend(rt_thread_self());
14. rt_schedule();
15. }
16. else
17. {
18. rt_tick_t current_tick;
19.
20. /* get current tick */
21. current_tick = rt_tick_get();//获取当前时间点
22.
23. if ((next_timeout - current_tick) < RT_TICK_MAX/2)//离下个中断时间点还差些时候
24. {
25. /* get the delta timeout tick */
26. next_timeout = next_timeout - current_tick;//计算还差多长时间
27. rt_thread_delay(next_timeout);//休眠一段时间
28. }
29. }
30.
31. /* lock scheduler */
32. rt_enter_critical();//时间到,进入临界区
33. /* check software timer */
34. rt_soft_timer_check();//检查是否该产生超时事件
35. /* unlock scheduler */
36. rt_exit_critical();//退出临界区
37. }
38.}
/*systemtimerthreadentry*/
staticvoidrt_thread_timer_entry(void*parameter)
{
rt_tick_tnext_timeout;
while
(1)
{
/*getthenexttimeouttick*/
next_timeout=rt_timer_list_next_timeout(&rt_soft_timer_list);//得到软件定时器链表上的下一个定时器的超时时间点
if(next_timeout==RT_TICK_MAX)//如果超过范围,则挂起当前线程,继续线程调度
{
/*nosoftwaretimerexist,suspendself.*/
rt_thread_suspend(rt_thread_self());
rt_schedule();
}
else
{
rt_tick_tcurrent_tick;
/*getcurrenttick*/
current_tick=rt_tick_get();//获取当前时间点
if((next_timeout-current_tick) { /*getthedeltatimeouttick*/ next_timeout=next_timeout-current_tick;//计算还差多长时间 rt_thread_delay(next_timeout);//休眠一段时间 } } /*lockscheduler*/ rt_enter_critical();//时间到,进入临界区 /*checksoftwaretimer*/ rt_soft_timer_check();//检查是否该产生超时事件 /*unlockscheduler*/ rt_exit_critical();//退出临界区 } } 检查是否产生中断函数rt_soft_timer_check函数如下定义: [cpp]viewplaincopyprint? 1./** 2. * This function will check timer list, if a timeout event happens, the 3. * corresponding timeout function will be invoked. 4. */ 5.void rt_soft_timer_check(void) 6.{ 7. rt_tick_t current_tick; 8. rt_list_t *n; 9. struct rt_timer *t; 10. 11. RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check enter\n")); 12. 13. current_tick = rt_tick_get();//得到当前时间点 14. 15. for (n = rt_soft_timer_list.next; n ! = &(rt_soft_timer_list);)//得到下一定时器节点 16. { 17. t = rt_list_entry(n, struct rt_timer, list);//t指向rt_timer定时器 18. 19. /* 20. * It supposes that the new tick shall less than the half duration of 21. * tick max. 22. */ 23. if ((current_tick - t->timeout_tick) < RT_TICK_MAX / 2)//如果当前的时间点超过定时器的超时时间点 24. { 25. RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t));//使用钩子函数 26. 27. /* move node to the next */ 28. n = n->next;//指向下一定时器 29. 30. /* remove timer from timer list firstly */ 31. rt_list_remove(&(t->list));//移除当前定时器 32. 33. /* call timeout function */ 34. t->timeout_func(t->parameter);//产生定时器超时事件,调用对应处理函数 35. 36. /* re-get tick */ 37. current_tick = rt_tick_get();//再次获取当前时间点 38. 39. RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick)); 40. 41. if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&//如果当前定时器是周期性定时器,则将其再次按序放入软件定时器链表 42. (t->parent.flag & RT_TIMER_FLAG_ACTIVATED)) 43. { 44. /* start it */ 45. t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;//置标志为非激活状态 46. rt_timer_start(t);//再次将定时器t放入软件定时器链表末尾 47. } 48. else 49. { 50. /* stop timer */ 51. t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;//置标志为非激活状态 52. } 53. } 54. else break; /* not check anymore */ 55. } 56. 57. RT_DEBUG_LOG(RT_DEBUG_TIMER, ("software timer check leave\n")); 58.} /** *Thisfunctionwillchecktimerlist,ifatimeouteventhappens,the *correspondingtimeoutfunctionwillbeinvoked. */ voidrt_soft_timer_check(void) { rt_tick_tcurrent_tick; rt_list_t*n; structrt_timer*t; RT_DEBUG_LOG(RT_DEBUG_TIMER,("softwaretimercheckenter\n")); current_tick=rt_tick_get();//得到当前时间点 for(n=rt_soft_timer_list.next;n! =&(rt_soft_timer_list);)//得到下一定时器节点 { t=rt_list_entry(n,structrt_timer,list);//t指向rt_timer定时器 /* *Itsupposesthatthenewtickshalllessthanthehalfdurationof *tickmax. */ if((current_tick-t->timeout_tick) { RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook,(t));//使用钩子函数 /*movenodetothenext*/ n=n->next;//指向下一定时器 /*removetimerfromtimerlistfirstly*/ rt_list_remove(&(t->list));//移除当前定时器 /*calltimeoutfunction*/ t->timeout_func(t->parameter);//产生定时器超时事件,调用对应处理函数 /*re-gettick*/ current_tick=rt_tick_get();//再次获取当前时间点 RT_DEBUG_LOG(RT_DEBUG_TIMER,("currenttick: %d\n",current_tick)); if((t->parent.flag&RT_TIMER_FLAG_PERIODIC)&&//如果当前定时器是周期性定时器,则将其再次按序放入软件定时器链表 (t->parent.flag&RT_TIMER_FLAG_ACTIVATED)) { /*startit*/ t->parent.flag&=~RT_TIMER_FLAG_ACTIVATED;//置标志为非激活状态 rt_timer_start(t);//再次将定时器t放入软件定时器链表末尾 } else { /*stoptimer*/ t->parent.flag&=~RT_TIMER_FLAG_ACTIVATED;//置标志为非激活状态 } } elsebreak;/*notcheckanymore*/ } RT_DEBUG_LOG(RT_DEBUG_TIMER,("softwaretimercheckleave\n")); } 上面代码中,为什么定时器里判断超时的条件是((current_tick-t→timeout_tick) 因为系统时钟溢出后会自动回绕。 取定时器比较最大值是定时器最大值的一半,即RT_TICK_MAX/2(在比较两个定时器值时,值是32位无符号数,相减运算将会自动回绕)。 系统支持的定时器最大长度就是RT_TICK_MAX的一半: 即248天(10ms/tick),124天(5ms/tick),24.5天(1ms/tick),以下内容相同道理。 其上rt_timer_start函数如下定义: [cpp]viewplaincopyprint? 1./** 2. * This function will start the timer 3. * 4. * @param timer the timer to be started 5. * 6. * @return the operation status, RT_EOK on OK, -RT_ERROR on error 7. */ 8.rt_err_t rt_timer_start(rt_timer_t timer) 9.{ 10. struct rt_timer *t; 11. register rt_base_t level; 12. rt_list_t *n, *timer_list; 13. 14. /* timer
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 整理rtthread 的定时器管理源码分析 整理 rtthread 定时器 管理 源码 分析