立即注册
查看: 750|回复: 6

[MTK软件经验分享] MTK timer分析总结

已绑定手机
发表于 2022-3-24 10:47:44 | 显示全部楼层 |阅读模式 来自 广东省深圳市
小结一:
MTK timer 有很多种,从最低层的KAL(kernel adpat layer)到MMI,都有timer的身影。
一、KAL的timer
KAL timer 是非常底层的timer, 它的实现是直接封装MTK的RTOS(nuleus)的timer,实现方式是由HISR,从而这种timer具有很高的优先级,也就是说,当这个timer 超时时,就会触发一个HISR(高级中断 High Level ISR (Interrupt Service Routine)),这个中断会回调注册的回调函数。所以这种timer 使用时,要比较小心,它的优先级很高,在回调函数运行时,其他事件是得不到处理的。

//创建一个timer, 参数是timer的名字
kal_timerid kal_create_timer(kal_char* timer_name_ptr); void

//设置timer 超时时间, timer_id 是 create 返回值,handler_func_ptr是回调函数,handler_param_ptr 是回调函数返回的参数(一般回调函数都是这么设置,这样很灵活),delay,是超时时间,注意这个参数的单位是ticks 不是ms。reschedule_time 表示是否循环使用timer,0 表示 timer 超时一次就停止,1 表示自动循环启动timer。
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);   
 
二、stack timer
这种timer 与 KAL timer 最大的区别是:stack timer 超时后,发送一个超时消息到相应task的消息队列,由task的消息队列来处理这个消息,而不像KAL timer,直接在中断状态回调注册函数。从时间的精确性来说,stack timer 可能没有KAL timer 精确(发送消息,task 切换等都要花费时间),但是 stack 更加的安全(在 task 里处理这个消息),提高并发性(stack timer 到期后只是发送了一个消息,具体并不处理)。当然 stack timer 底层具体实现还是依靠KAL timer。有一点需要注意的是,当stack timer 超时后,向消息队列发送了消息,但是这个消息还没有来的处理,这个时候取消了这个timer,需要特别处理,虽然这种情况发生的概率很小。

// stack timer 初始化 module_id 是要接受消息的 mdoule,也就是当stack timer 超时,会向该module 发送消息。
void stack_init_timer(stack_timer_struct *stack_timer, kal_char *timer_name, module_type module_id);

//判断这个消息是否继续有效,也就是是否需要处理,这个函数就是用于方式上面提到那种情况的发生。
kal_bool stack_is_time_out_valid(stack_timer_struct *stack_timer);

//这个函数与上面的函数成对使用,具体看例子。
void stack_process_time_out(stack_timer_struct *stack_timer); void

//启动定时期,timer_index  timer 索引, 超时时间。
stack_start_timer(stack_timer_struct *stack_timer, kal_uint16 timer_indx, kal_uint32 init_time);

小结二:
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的准确度,这个参数的作用主要是用于节省电池。

//设置一个timer,es 用 new_evshed 创建的,event_hf, timer 超时后的回调函数,event_hf_param 回调函数传入的参数,elapse_time timer的时间。
extern eventid evshed_set_event(event_scheduler *es,
                                kal_timer_func_ptr event_hf,
                                void *event_hf_param,
                                kal_uint32 elapse_time);

//时间超时后,统一处理超时回调函数。也就是说,当stack timer 向相应的mod 发送 MSG_ID_TIMER_EXPIRY后,需要调用该函数,该函数会处理相应的回调函数。
extern void evshed_timer_handler(event_scheduler *es);

MTK 的这套机制让人感觉很别扭,像 evshed_timer_handler 这样的函数都要手动去调用,仔细想想,也只能这么来用,event scheduler 依赖于 stack timer, 而stack timer 又只能往相应的mod 里发送消息,而这个mod的消息处理又是自己手动写的,如果不开放 evshed_timer_handler 这个函数,那么超时了,event scheduler 也不知道。
下面举了个例子,就上面这么一说,估计也是晕晕的,我当时看了N遍代码,才慢慢明白些,也没有个资料可以参考。
就看MMI timer的实现,平时开发应用的时候,这个是用的最多的。

更多详细内容请下载附件查看
游客,如果您要查看本帖隐藏内容请回复
发表于 2022-3-24 17:50:10 | 显示全部楼层 来自 上海市
学习学习
已绑定手机
发表于 2022-3-24 17:52:19 | 显示全部楼层 来自 上海市
谢谢分享·
已绑定手机
已实名认证
发表于 2022-3-25 08:00:53 | 显示全部楼层 来自 广东省深圳市
谢谢分享。555
已绑定手机
发表于 2022-3-25 08:49:56 | 显示全部楼层 来自 湖北省武汉市
感谢分享~~~~~~~~~~~
已绑定手机
发表于 2022-3-25 09:06:05 | 显示全部楼层 来自 广东省深圳市
9999999999999999999
已绑定手机
发表于 2022-5-5 11:33:59 | 显示全部楼层 来自 浙江省宁波市
看看 学习学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

合作/建议

TEL: 19168984579

工作时间:
周一到周五 9:00-11:30 13:30-19:30
  • 扫一扫关注公众号
  • 扫一扫打开小程序
Copyright © 2013-2024 一牛网 版权所有 All Rights Reserved. 帮助中心|隐私声明|联系我们|手机版|粤ICP备13053961号|营业执照|EDI证
在本版发帖搜索
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表