MTK timer 小结 3

在 MTK timer 小结 2 说道最常用的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 don't start the timer */         MMI_ASSERT(0);         return;     }      MMI_ASSERT(nTimerId < MAX_TIMERS);      if (L4TimerUsePreciseTick(nTimerId))     {         alignment = TIMER_IS_NO_ALIGNMENT;     }       // 把 ticks 转化为ms     // mtk 底层的timer 的单位都是 ticks     if (nTimeDuration == 1000)     {         temp = KAL_TICKS_1_SEC - 4;     }     else     {         temp = (U32)((nTimeDuration / 5) * MMI_TICKS_5_MSEC);     }      if (temp == 0)     {         /* Cause by by rounding. If expire immediately, MoDIS boot-up failure because MMI keeps running and block NVRAM task */         temp = (U32)MMI_TICKS_5_MSEC;     }      //取得存放所有MMI timer 的table     // 在 MTK timer 小结 2 中提到,这个table 是 list + array 组合     // 如果只用存数组的话,初始化大小不好确定,而且要 array relloc. 如果考虑内存回收还容易引起数组震荡     // 如果只用list的话,一个timer如果很频繁的话,会不停的malloc 和 free     pTable = &g_timer_table;      //判断timer 是否已经 满了     // 如果满了,那么需要在timer table 后面增加一个timer node     if (g_timer_table_used >= 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->tm[i].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)         {             /* Can't find the empty space in TIMERTABLE list, assert!!! */             MMI_ASSERT(0);         }     }   /* if (g_timer_table_used >= g_timer_table_size) */      // 根据 algigment 属性,分别创建一个 event scheduler timer     // 把 timer 的信息保存到 timer node 里面     if (alignment == TIMER_IS_NO_ALIGNMENT)     {         /* MSB(Most Significant Bit) is align_timer_mask */         pTable->tm[i].timer_info = nTimerId | NO_ALIGNMENT_TIMER_MASK;         pTable->tm[i].event_id = evshed_set_event(                                     event_scheduler1_ptr,                                     (kal_timer_func_ptr) L4CallBackTimer,                                     (void*)&(pTable->tm[i]),                                     temp);         pTable->tm[i].arg = funcArg;         pTable->tm[i].callback_func = TimerExpiry;         g_timer_table_used++;     }     else if (alignment == TIMER_IS_ALIGNMENT)     {         /* MSB(Most Significant Bit) is align_timer_mask */         pTable->tm[i].timer_info = nTimerId | ALIGNMENT_TIMER_MASK;         pTable->tm[i].event_id = evshed_set_event(                                     event_scheduler2_ptr,                                     (kal_timer_func_ptr) L4CallBackTimer,                                     (void*)&(pTable->tm[i]),                                     temp);         pTable->tm[i].arg = funcArg;         pTable->tm[i].callback_func = TimerExpiry;         g_timer_table_used++;     } }
再说一句 timer table,其实也可以用 timer pool 来实现,把超时或者stop的timer node,放入到free pool 中,需要时再拿出来,也可以避免重复的malloc 和 free。
在 设置 event scheduler timer 中,设置了一个回调函数 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     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。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值