APM 任务调度器的原理分析

  1 APM Scheduler 分析
  2 
  3 void AP_Scheduler::run(uint32_t time_available)
  4 {
  5     uint32_t run_started_usec = AP_HAL::micros();
  6     uint32_t now = run_started_usec;
  7 
  8     for (uint8_t i=0; i<_num_tasks; i++) {
  9         // dt代表了当前任务已经调度了多少个周期
 10         uint16_t dt = _tick_counter - _last_run[i];
 11 
 12         // interval_ticks代表这个任务需要多少个调度周期才能运行
 13         // 如果任务调度周期(_loop_rate_hz)设置成50hz,也就是说20ms调度一次, _tick_counter+1
 14         // 如果一个任务被设置成以10hz运行,也就是100ms运行一次,需要进行50hz/10hz=5次调度,此任务才能被运行一次
 15         uint16_t interval_ticks = _loop_rate_hz / _tasks[i].rate_hz;
 16 
 17         // 如果调度次数小于1,也就是说任务调度的频率比_loop_rate_hz还快,则只调度一次
 18         // 这里通过_loop_rate_hz限制了任务调度的最快频率
 19         if (interval_ticks < 1) { 
 20             interval_ticks = 1;
 21         }
 22 
 23         // 如果dt>=interval_ticks,代表当前任务已经达到了所需调度的周期,可以进行调度了
 24         if (dt >= interval_ticks) {
 25             // _task_time_allowed代表了当前任务最大允许被运行的时间
 26             // 这个时间在这个调度策略中并无卵用,纯属鸡肋!!!
 27             // 不好意思,也并不是完全鸡肋,他的作用体现在当调度器剩余时间是否够当前任务最大所需时间
 28             
 29             // this task is due to run. Do we have enough time to run it?
 30             _task_time_allowed = _tasks[i].max_time_micros;
 31 
 32             // 当前任务所需的调度周期已经超过2次所需时间,代表此任务本应该被执行了,但是被延迟了
 33             // 此处没有做任何处理,只是做了调试输出
 34             // 所以说每个任务即使你规定了他的调度频率,只是一个期望值,他受到整个系统调度的影响,他的实时性是不确定的
 35             if (dt >= interval_ticks*2) {
 36                 // we've slipped a whole run of this task!
 37                 if (_debug > 4) {
 38                     ::printf("Scheduler slip task[%u-%s] (%u/%u/%u)\n",
 39                              (unsigned)i,
 40                              _tasks[i].name,
 41                              (unsigned)dt,
 42                              (unsigned)interval_ticks,
 43                              (unsigned)_task_time_allowed);
 44                 }
 45             }
 46 
 47             // time_available代表当前调度器还剩余多少时间来进行任务调度
 48      // time_available = 1000000/_loop_rate_hz= 20ms
 49             // 如果当前任务单次最大被允许运行的时间比剩余的时间还小,证明系统还有足够的时间来运行他,那么就可以运行此次任务
 50             // 否则跳出,继续轮训列表中的下一次任务,看谁还有机会被执行
 51             if (_task_time_allowed <= time_available) {
 52                 // run it
 53                 //记下当前任务运行的开始时间
 54                 _task_time_started = now;
 55                 current_task = i;
 56                 _tasks[i].function();
 57                 current_task = -1;
 58 
 59                 // 更新当前任务运行完成后的tick,为计算下一次dt做准备
 60                 // record the tick counter when we ran. This drives
 61                 // when we next run the event
 62                 _last_run[i] = _tick_counter;
 63 
 64                 // work out how long the event actually took
 65                 now = AP_HAL::micros();
 66                 // 计算出当前任务运行的时间
 67                 uint32_t time_taken = now - _task_time_started;
 68 
 69                 // 如果当前任务运行的时间超过了最大允许的时间,代表当前任务已经超时运行
 70                 // 这里只是做了打印输出,并没有什么卵用
 71                 if (time_taken > _task_time_allowed) {
 72                     // the event overran!
 73                     if (_debug > 4) {
 74                         ::printf("Scheduler overrun task[%u-%s] (%u/%u)\n",
 75                                  (unsigned)i,
 76                                  _tasks[i].name,
 77                                  (unsigned)time_taken,
 78                                  (unsigned)_task_time_allowed);
 79                     }
 80                 }
 81                 // 如果当前任务运行的时间已经超过调度器剩余的时间,那么就直接退出任务列表调度
 82  // 但前任务后面的任务就不调度了
 83                 if (time_taken >= time_available) {
 84                     goto update_spare_ticks;
 85                 }
 86                 // 把调度器剩余可用的时间更新,如果当前任务超时运行,那么下一个任务就可能执行不到了
 87                 time_available -= time_taken;
 88             }
 89         }
 90     }
 91 
 92     // update number of spare microseconds
 93     _spare_micros += time_available;
 94 
 95 update_spare_ticks:
 96     _spare_ticks++;
 97     if (_spare_ticks == 32) {
 98         _spare_ticks /= 2;
 99         _spare_micros /= 2;
100     }
101 }

猜你喜欢

转载自www.cnblogs.com/jingjin666/p/11131255.html
APM
今日推荐