美文网首页RTOS和GUI_基于英飞凌tc2x及stm32开发板
etas os事件激活任务源码分析--Apple的学习笔记

etas os事件激活任务源码分析--Apple的学习笔记

作者: applecai | 来源:发表于2023-06-13 22:09 被阅读0次

    一,前言

    之前已经看了alarm和调度表的切换代码设计,基本上就是match和dispatch,那么这个event事件激活我基本上可以猜测出来了。应该是调用激活的时候设置match,然后就按优先级调用dispatch,去看看源码吧

    二,源码分析

    1.Os_WaitEvent
    此函数主要目的是设置taskdyn->waiting_events标志位,然后此时set event也置1,了,那么直接运行,否则else就是把当前任务挂起,也就是设置Os_WaitingTasks.p1标志位,然后会调用Os_setjmp和Os_longjmp进行任务切换,这里居然没有调用os_dispatch,属于直接切换。

      if ((taskdyn->waiting_events & taskdyn->set_events) != 0U) {
        /* Return immediately  [$UKS 140] */
        Os_CurrentMeteredObject->stackbudget = Os_RunningTask->stackbudget;
        Os_CurrentMeteredObject->stackusage.sp = 0U; Os_CurrentMeteredObject->stackusage.ctx = 0U;
      } else {
        /* Become waiting */ /* [$UKS 167] [$UKS 155] [$UKS 837] */
        Os_WaitingTasks.p1 |= Os_RunningTask->pset.p1; /*lint !e931 PC-lint thinks there are side effects here */
    
    1. Os_ClearEvent
      主要目的是清除Os_RunningTask->dynamic->set_events标志。
    2. ActivateTask
      Pizza的example中调用了ActiveTask,由于优先级高就直接调用os_dispatch切换任务了,在此task调用了SetRelAlarm(Doorbell, Duration, 0U);其中Doorbell就是事件mask值。此函数中主要调用Os_CounterRelativeStart(ctr,increment,&Os_dyn_alarms[AlarmID].match);来设置期望的match值,看到match值就知道是tick加1的地方处理了。也就是tick中断函数IncrementCounter(MillisecondCounter)中,相比周期alarm生成的code中仅有Os_ActivateTaskKL,而带event的就会生成Os_SetEventKL.
          cfg_index = (cref->config & 3U);
          if (cfg_index > 0U) {
            EventMaskType ev = (EventMaskType)((cref->config & 4U) >> 2U);
            if (ev != 0U) {Os_SetEventKL(Os_const_tasks[cfg_index - 1U], ev);} else { Os_ActivateTaskKL(Os_const_tasks[cfg_index - 1U], os_current_core_const, os_current_controlled_core);}
          }
    

    Os_SetEventKL函数中主要就是设置TaskID->dynamic->set_events标志,然后若之前有waiting_events 的,那么就设置就绪ReadyTasks标志,最后就是os_dispatch切换任务了。

            /* Set the event */
            TaskID->dynamic->set_events |= Mask; /* [$UKS 146] [$UKS 147] [$UKS 1760] */
          
            if ((TaskID->ecc->events & TaskID->dynamic->waiting_events & TaskID->dynamic->set_events) != 0U) {
              /* Ready the task if not already ready */
              if (!(0U != (Os_ControlledCoreInfo[1U].ReadyTasks.p1 & TaskID->pset.p1)) ) {
                /* [$UKS 145] Need to resume from WaitEvent */
                Os_ControlledCoreInfo[1U].ReadyTasks.p1 |= TaskID->pset.p1; 
    

    三,小结

    看了源码设计思路就比较清晰了,关键就是调用SetRelAlarm来set event及match值和waitevent,wait的task调用过程中event已经set就直接继续运行这个task,否则就切换task,另外一个是已经set event了,然后tick心跳中判断有wait挂起的任务就进行就绪准备了。只是Os_SetRelAlarm中仅设置match时间并没有设置event,event是在tick心跳中设置的,说明不能直接就绪事件任务(所以事件一般都有一个等待事件和设置事件的概念)。若想直接就绪任务直接调用ActivateTask即可。这么看下源码对事件挂起和就绪理解的更加清晰了,达到了闭环理解理论需求的目的,时间没白花,哈哈~

    相关文章

      网友评论

        本文标题:etas os事件激活任务源码分析--Apple的学习笔记

        本文链接:https://www.haomeiwen.com/subject/xavtydtx.html