




免费预览已结束,剩余5页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
M T K timer 小结 1MTK 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 使用时,要比较小心,它的优先级很高,在回调函数运行时,其他事件是得不到处理的。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 超时时间, timer_id 是 create 返回值,handler_func_ptr是回调函数,handler_param_ptr 是回调函数返回的参数(一般回调函数都是这么设置,这样很灵活),delay,是超时时间,注意这个参数的单位是ticks 不是ms。reschedule_time 表示是否循环使用timer,0 表示 timer 超时一次就停止,1 表示自动循环启动timer。第二种timer 是 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,此时需要特别处理,虽然这种情况发生的概率很小。void stack_init_timer(stack_timer_struct *stack_timer, kal_char *timer_name, module_type module_id);/ stack timer 初始化 module_id 是要接受消息的mdoule,也就是当stack timer 超时,会向该module发送消息。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, kal_uint16 timer_indx, kal_uint32 init_time); /启动定时期,timer_index timer 索引, 超时时间。M T K timer 小结 2在 MTK timer 小结 1 提到了两种timer,KAL timer 和 stack timer, 这两种timer 在平时用的比较少,在驱动开发,或者时间要求特别精确的情况下,使用 KAL timer, 一般在task要管理一组timer,用 stack timer 加上 event scheduler,后者就是今天要介绍的第三种timer。第三种timer: event schedulerevent 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 (module)发送 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 是一种 链表 加上 数组的实现。这样实现 可以省去一些内存的频繁申请和释放。 MTK timer 小结 3前面提到最常用的MMI timer 实现机制的初始化过程。今天继续往下说,下面要说的是创建一个timer。MMI 层,启动一个timer,最终都会调用到 L4StartTimer 这个函数。具体来分析一下这个函数/ 参数 nTimerId 是要自己定义一个timer id,在 timerEvents.h 里的 MMI_TIMER_IDS 定义,用来区分timer/ TimerExpiry 超时的回调函数/ funcArg 回调函数回传的参数/ nTimeDuration 超时时间,单位ms/ alignment alignment或者non-alignment,在MTK timer 小结 2 说明过static void L4StartTimer( unsigned short nTimerId, oslTimerFuncPtr TimerExpiry, void *funcArg, unsigned long nTimeDuration, unsigned char alignment) /*-*/ /* Local Variables */ /*-*/ TIMERTABLE *pTable = NULL; U16 i = 0; U32 temp; /*-*/ /* Code Body */ /*-*/ if (TimerExpiry = NULL) /* If TimerExpiry is NULL, we dont start the timer */ MMI_ASSERT(0); return; MMI_ASSERT(nTimerId = g_timer_table_size) do if (pTable-next = NULL) pTable-next = OslMalloc(sizeof(TIMERTABLE); memset(pTable-next, 0, sizeof(TIMERTABLE); g_timer_table_size += SIMULTANEOUS_TIMER_NUM; pTable = pTable-next; i = 0; break; pTable = pTable-next; while (pTable != NULL); else /寻找空的 timer node i = 0; do if (pTable-tmi.event_id = NULL) /* find the empty space */ break; i+; if (i = SIMULTANEOUS_TIMER_NUM) pTable = pTable-next; i = 0; while (pTable != NULL); if (pTable = NULL) /* Cant find the empty space in TIMERTABLE list, assert! */ MMI_ASSERT(0); /* if (g_timer_table_used = g_timer_table_size) */ / 根据 alignment 属性,分别创建一个 event scheduler timer / 把 timer 的信息保存到 timer node 里面 if (alignment = TIMER_IS_NO_ALIGNMENT) /* MSB(Most Significant Bit) is align_timer_mask */ pTable-tmi.timer_info = nTimerId | NO_ALIGNMENT_TIMER_MASK; pTable-tmi.event_id = evshed_set_event( event_scheduler1_ptr, (kal_timer_func_ptr) L4CallBackTimer, (void*)&(pTable-tmi), temp); pTable-tmi.arg = funcArg; pTable-tmi.callback_func = TimerExpiry; g_timer_table_used+; else if (alignment = TIMER_IS_ALIGNMENT) /* MSB(Most Significant Bit) is align_timer_mask */ pTable-tmi.timer_info = nTimerId | ALIGNMENT_TIMER_MASK; pTable-tmi.event_id = evshed_set_event( event_scheduler2_ptr, (kal_timer_func_ptr) L4CallBackTimer, (void*)&(pTable-tmi), temp); pTable-tmi.arg = funcArg; pTable-tmi.callback_func = TimerExpiry; g_timer_table_used+; 再说一句 timer table,其实也可以用 timer pool 来实现,把超时或者stop的timer node,放入到free pool 中,需要时再拿出来,也可以避免重复的malloc 和 free。在设置 event scheduler timer 中(是eventid evshed_set_event()吗?),设置了一个回调函数 L4CallBackTimer, 这个回调函数就是在 stack timer 超时需要回调的函数。那具体再哪里回调?在 MTK timer 小结 2 提到, event scheduler 还是依赖于stack timer,在 MTK timer 小结 1 提到 stack timer 超时后是向相应的mod 发送消息。在初始化L4InitTimer函数中,stack timer 初始化(stack_init_timer(&base_timer1, MMI_Base_Timer1, MOD_MMI)时mod 是 MOD_MMI,那么超时后,就会向 mmi task 发送超时消息。MMI层在MMI_task 函数中处理所有的消息,while 消息处理中,可以看到 case MSG_ID_TIMER_EXPIRY: kal_uint16 msg_len; EvshedMMITimerHandler(get_local_para_ptr(Message.oslDataPtr, &msg_len);break;这个就是处理 stack timer 地方。也就是stack timer 超时后,会回调 EvshedMMITimerHandler 函数。void EvshedMMITimerHandler(void *dataPtr) /*-*/ /* Local Variables */ /*-*/ stack_timer_struct *stack_timer_ptr; stack_timer_ptr = (stack_timer_struct*) dataPtr; /*-*/ /* Code Body */ /*-*/ / 判断是哪种stack timer,队列型(alignment timer)OR非队列型(no alignment timer) if (stack_timer_ptr = &base_timer1) / 这里需要判断这 stack timer 是否还是有效,也就是否被stop / 这种情况出现环境在 MTK timer 小结 1 中介绍过 / 如果无效,就不要触发这个timer if (stack_is_time_out_valid(&base_timer1) /调用 这个函数,处罚注册的 event scheduler timer evshed_timer_handler(event_scheduler1_ptr); stack_process_time_out(&base_timer1); else if (stack_timer_ptr = &base_timer2) if (stack_is_time_out_valid(&base_timer2) evshed_timer_handler(event_scheduler2_ptr); stack_process_time_out(&base_timer2); 这个函数在调用evshed_timer_handler函数时,就会回调由 evshed_set_event 注册的timer 回调函数 L4CallBackTimer。MTK timer 小结 4 昨天说到回调函数 L4CallBackTimer。static void L4CallBackTimer(void *p) / 在evshed_set_event 第三个参数中传得 timer noder / 这里转换这个指针 mmi_frm_timer_type *pTimer = (mmi_frm_timer_type *)p; / 得到timer id U32 nTimerId = pTimer-timer_info & (NO_ALIGNMENT_TIMER_MASK); / 得到回调函数 oslTimerFuncPtr pTimerExpiry = pTimer-callback_func; / 得到 回调 函数参数 void * arg = pTimer-arg; / timer 个数减少 g_timer_table_used-; / 清空这个 timer nodeme
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 粮油会计考试题库及答案
- 森林防火知识培训报告课件
- 八大员的质量员(设备安装专业)考试题及答案(完整版)
- 2025年中级厨师长专业烹饪技能考试试题集
- 2025年数据分析面试题融媒体集
- 2025年高级数字殡葬规划师专业能力评估题库及参考答案详解
- 2025年老年病管理试题及答案
- 2025年人工智能技术应用工程师职称考试模拟题
- 2025年基础设施发展与经济促进试题及答案
- 2025年注册验船师资格考试(A级船舶检验专业案例分析)自测试题及答案二
- 2025年广西中考物理真题含答案
- 服装工艺培训课件
- 2025至2030中国股指期货行业发展分析及发展前景与投资报告
- 美术介绍教学课件
- 脑梗死合并高血压护理查房
- 2025年福建省福州左海供应链集团有限公司招聘笔试参考题库含答案解析
- 2025届上海市中考语文真题作文题目解析+范文
- 暖通运维面试题库及答案
- 中西医结合治疗过敏性疾病的实践与思考
- 路面注浆打孔合同范本
- 新疆维吾尔自治区巴音郭楞蒙古自治州2024-2025学年八年级下学期期末模拟数学试题(无答案)
评论
0/150
提交评论