RTOS和GUI_基于英飞凌tc2x及stm32开发板

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

2023-06-13  本文已影响0人  applecai

一,前言

之前已经看了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即可。这么看下源码对事件挂起和就绪理解的更加清晰了,达到了闭环理解理论需求的目的,时间没白花,哈哈~

上一篇下一篇

猜你喜欢

热点阅读