在 MTK timer 小结 1 提到了两种timer,KAL timer 和 stack timer, 这两种timer 在平时用的比较少,在驱动开发,或者时间要求特别精确的情况下,使用 KAL timer, 一般在task要管理一组timer,用 stack timer 加上 event scheduler,后者就是今天要介绍的第三种timer。
event scheduler 处理的timer 时间精确性上来说,相对不是那么精确,对于上层app应用来说,是必不可少的。MMI 层的timer(StartTimer 系列函数) 就是用event scheduler + stack timer 来实现的。
extern event_scheduler *new_evshed(void *timer_id,
void (*start_timer)(void *, unsigned int),
void (*stop_timer)(void *),
kal_uint32 fuzz,
malloc_fp_t alloc_fn_p,
free_fp_t free_fn_p,
kal_uint8 max_delay_ticks);创建一个 event scheduler , timer_id 是stack timer 创建的timer id,一般称为base timer,start_timer 启动这个base timer, stop_timer 停止这个base timer,fuzz 校正timer 时间,alloc_fn_p 内存分配函数,free_fn_p 内存释放函数,max_delay_ticks timer 最大可延迟时间,这个表示timer的准确度,这个参数的作用主要是用于节省电池。
extern eventid evshed_set_event(event_scheduler *es,
kal_timer_func_ptr event_hf,
void *event_hf_param,
kal_uint32 elapse_time);设置一个timer,es 用 new_evshed 创建的,event_hf, timer 超时后的回调函数,event_hf_param 回调函数传入的参数,elapse_time timer的时间。
extern void evshed_timer_handler(event_scheduler *es);
时间超时后,统一处理超时回调函数。也就是说,当stack timer 向 相应的mod 发送 MSG_ID_TIMER_EXPIRY后,需要调用该函数,该函数会处理相应的回调函数。
MTK 的这套机制让人感觉很别扭,像 evshed_timer_handler 这样的函数都要手动去调用,仔细想想,也只能这么来用,event scheduler 依赖于 stack timer, 而stack timer 又只能往相应的mod 里发送消息,而这个mod的消息处理又是自己手动写的,如果不开放 evshed_timer_handler 这个函数,那么超时了,event scheduler 也不知道。 不过还是别扭阿
下面举了个例子,就上面这么一说,估计也是晕晕的,我当时看了N遍代码,才慢慢明白些,也没有个资料可以参考。
就看MMI timer的实现,平时开发应用的时候,这个是用的最多的。
源文件:MMITimer.c
先来看初始化函数:
void L4InitTimer(void) { TIMERTABLE *p; TIMERTABLE *pp; // 1 释放timer table 内存 p = g_timer_table.next; pp = NULL; do { if (p != NULL) { pp = p->next; OslMfree(p); } p = pp; } while (p != NULL); /* reset g_timer_talbe */ memset(&g_timer_table, 0, sizeof(TIMERTABLE)); g_timer_table_size = SIMULTANEOUS_TIMER_NUM; g_timer_table_used = 0; /* Initiate the clock time callback function. */ get_clocktime_callback_func = NULL; set_clocktime_callback_func = NULL; //2 初始化 stack timer 1 /* Initate the no alignment stack timer */ stack_init_timer(&base_timer1, "MMI_Base_Timer1", MOD_MMI); //3 根据 stack timer 1 ,创建 event scheduler 1 /* Create a no alignment timer schedule */ event_scheduler1_ptr = new_evshed( &base_timer1, L4StartBaseTimer, L4StopBaseTimer, 0, kal_evshed_get_mem, kal_evshed_free_mem, 0); //4 初始化 stack timer 2 /* Initate the alignment stack timer */ stack_init_timer(&base_timer2, "MMI_Base_Timer2", MOD_MMI); //5 根据 stack timer 2 创建 event scheduler 2 /* Create an alignment timer schedule */ event_scheduler2_ptr = new_evshed( &base_timer2, L4StartBaseTimer, L4StopBaseTimer, 0, kal_evshed_get_mem, kal_evshed_free_mem, 254); }
说明:MMI 共有两种timer,一种是 no alignment timer ,一种叫 alignment timer。
两者的区别有两点:
1,前置不会延迟,也就是说相对于后来来说,精确很多,当然后者有可能延迟,也就是用后者创建了一个100ms timer ,也许过了 150ms 才被回调 ,甚至 300ms。
2,前置在手机休眠时不会被关起,二后会被挂起,也就是如果用后者创建了一个timer,还没有到期,这个时候手机休眠了,那么这个timer就不会被触发了,知道手机再次唤醒。
在MMI timer 里面,这两种timer 分别对应 event_scheduler1_ptr 和 event_scheduler2_ptr。
在 MMI 实现timer 里面用了一种 table,用来存放每一个timer的信息,这种table 是一种 链表 加上 数组的实现。
这样实现 可以省去一些内存的频繁申请和释放。
转自:
http://blog.csdn.net/yanwuxufeng/archive/2010/07/19/5748114.aspx