MTK中有两种timer,KAL timer 和 stack timer. 一般在task要管理一组timer,用 stack timer 加上 event scheduler.现在主要介绍这种
KAL timer 是非常底层的timer, 它的实现是直接封装MTK的RTOS(nuleus)的timer,实现方式是由HISR,从而这种timer具有很高的优先级,当这个timer 超时时,就会触发一个HISR(高级中断 High Level ISR (Interrupt Service Routine)),这个中断会回调注册的回调函数。
kal_timerid kal_create_timer(kal_char* timer_name_ptr); //创建一个timer, 参数是timer的名字
void kal_set_timer(kal_timerid timer_id, //
kal_timer_func_ptr handler_func_ptr, //是回调函数
void* handler_param_ptr, //是回调函数返回的参数
kal_uint32 delay, //是超时时间
kal_uint32 reschedule_time); //表示是否循环使用timer,0 表示 timer 超时一次就停止,1 表示自动循环启动timer。
stack timer与 KAL timer 最大的区别是:stack timer 超时后,发送一个超时消息到 相应task的消息队列,由task的消息队列来处理这个消息,而不像KAL timer,直接在中断状态回调注册函数。从时间的精确性来说,stack timer 可能没有KAL timer 精确(发送消息,task 切换等都要花费时间),但是 stack 更加的安全(在 task 里处理这个消息),提高并发性(stack timer 到期后只是发送了一个消息,具体并不处理)。当然 stack timer 底层具体实现还是依靠KAL timer。
1. 常用函数
//函数作用:初始化定时器
void stack_init_timer(stack_timer_struct *stack_timer, //此为stack_timer_struct结构体指针
kal_char *timer_name, //名称,自己取
module_type module_id); //是要接受消息的 mdoule,也就是当stack timer 超时,会向该model 发送消息。
//函数作用:判断这个消息是否继续有效,也就是是否需要处理
kal_bool stack_is_time_out_valid(stack_timer_struct *stack_timer);
//函数作用:这个函数与上面的函数成对使用
void stack_process_time_out(stack_timer_struct *stack_timer);
///函数作用:启动定时期
void stack_start_timer(stack_timer_struct *stack_timer, //此为stack_timer_struct结构体指针
kal_uint16 timer_indx, // timer 索引
kal_uint32 init_time); // 超时时间
event scheduler 处理的timer 时间精确性上来说,相对不是那么精确,对于上层app应用来说,是必不可少的。MMI 层的timer(StartTimer 系列函数) 就是用event scheduler + stack timer 来实现的。
//函数作用:创建一个 event scheduler
extern event_scheduler *new_evshed(void *timer_id, //对应stack_init_timer函数中的struct_timer指针
void (*start_timer)(void *, unsigned int), //启动这个base timer
void (*stop_timer)(void *), //停止这个base timer
kal_uint32 fuzz, //校正timer 时间
malloc_fp_t alloc_fn_p, //内存分配函数
free_fp_t free_fn_p, //内存释放函数
kal_uint8 max_delay_ticks); //最大可延迟时间,这个表示timer的准确度
//函数作用:设置一个timer
extern eventid evshed_set_event(event_scheduler *es, //用 new_evshed 创建的
kal_timer_func_ptr event_hf, // timer 超时后的回调函数
void *event_hf_param, //回调函数传入的参数
kal_uint32 elapse_time); // timer的时间。
//函数作用: 时间超时后,统一处理超时回调函数。也就是说,当stack timer 向 相应的mod 发送 MSG_ID_TIMER_EXPIRY后,需要调用该函数,该函数会处理相应的回调函数。
extern void evshed_timer_handler(event_scheduler *es);
2. 数据结构
(1). stack_timer_struct //定时器类型的信息结构( 其主要作用似乎是用以装载待发送的定时器消息数据 )
(2). mmi_frm_timer_type //定时器信息结构 。如下图:
(3). TIMERTABLE //TIMERTABLE 是一种 链表 加上 数组的实现。具体结构如下:
定时器队列节点结构( 其由主要元素mmi_frm_timer_type结构及链表指针两个元素组成 )
(3). event_scheduler
队列信息结构,是一个双向循环链表
3. L4定时器初始化
(1). 步骤
创建MMI Task -> 设置MMI Task初始化函数 -> 在该函数中调用 L4InitTimer
(2). 作用:初始化定时器队列并设置基本定时器1,2
4. 发送定时器消息
(1). 步骤
StartTimer -> L4StartTimer
(2). MTK中有两种类型的定时器说明
*说明:MMI 共有两种timer,一种是 no alignment timer ,一种叫 alignment timer。
*两者的区别有两点:
*1,前置不会延迟,非队列式的,即要求立即执行的定时器,时间到了就自动被reset.
.也就是说相对于后来来说,精确很多,当然后者有可能延迟,也就是用后者创建了一个100ms timer ,也许过了 150ms 才被回调
*2,前置在手机休眠时不会被关起,二后会被挂起,也就是如果用后者创建了一个timer,还没有到期,这个时候手机休眠了,那么这个timer就不会被触发了,知道手机再次唤醒。
*在MMI timer 里面,这两种timer 分别对应 event_scheduler1_ptr 和 event_scheduler2_ptr。
*3 .除了触摸屏和手写,其他情况下的定时器一般都是队列式的.
5. 定时器消息的处理
(1)MMI 层 在 MMI_task 函数中处理所有的消息,while 消息处理中,可以看到
case MSG_ID_TIMER_EXPIRY:
{
kal_uint16 msg_len;