CleanFlight 源码分析 一,任务调度
CleanerFlight的任務調度用的是時間片查詢的方式。每個任務沒有自己的堆棧,不會進行強行跳轉。任何一個任務時間過長都會導致其它任務時間延遲(所以不要亂用Delay()).
A.基本的調度方式,如果當前系統時間 > (任務的最后一次運行時間+任務的運行周期),則執行當前任務,否則繼續查找到期的任務。
B.任務優先級,先查詢優先級數字低的任務,A, 遍歷完所有任務后,下個優先級
C.任務可以是事件驅動型,或者是周期型,或者兩者都是。先執行事件驅動,然后是周期運行。
D.系統時間,微秒計時。設置systick的中斷時間為1毫秒,中斷內負責毫秒計時,則
????? 微秒計數=毫秒計數 * 1000 + (系統時鐘頻率 / 1000 - systick計數值) / (系統時鐘頻率 / 1000000)
E.執行任務,使用函數指針指向當前任務函數,加入輸入變量即可運行:selectedTask->taskFunc(currentTimeUs),
系統工作步驟:
1.初始化任務列表
2.任務循環調度
任務系統就兩個文件:scheduler.h,scheduler.c
自定義任務:
[TASK_SERIAL] = {
? ? ? ? .taskName = "SERIAL",
? ? ? ? .taskFunc = taskHandleSerial,
#ifdef USE_OSD_SLAVE
? ? ? ? .checkFunc = taskSerialCheck,
? ? ? ? .desiredPeriod = TASK_PERIOD_HZ(100),
? ? ? ? .staticPriority = TASK_PRIORITY_REALTIME,
#else
? ? ? ? .desiredPeriod = TASK_PERIOD_HZ(1), ? ? ? // 100 Hz should be enough to flush up to 115 bytes @ 115200 baud
? ? ? ? .staticPriority = TASK_PRIORITY_LOW,
#endif
? ? },
任務內容:
void taskHandleSerial()
{
?? ?Serial_puts(USART3, "HELLODWORLD\n"); /*while (1);*/
}
允許任務運行:
setTaskEnabled(TASK_SERIAL, true);
任務開始:
void schedulerInit(void)
{
? ? calculateTaskStatistics = true;
? ? queueClear();
? ? queueAdd(&cfTasks[TASK_SYSTEM]);
}
任務調度:
void scheduler(void)
{
? ? // Cache currentTime
? ? const timeUs_t currentTimeUs = micros();
? ? // Check for realtime tasks
? ? bool outsideRealtimeGuardInterval = true;
? ? for (const cfTask_t *task = queueFirst(); task != NULL && task->staticPriority >= TASK_PRIORITY_REALTIME; task = queueNext())
? ? {
? ? ? ? const timeUs_t nextExecuteAt = task->lastExecutedAt + task->desiredPeriod;
? ? ? ? if ((timeDelta_t)(currentTimeUs - nextExecuteAt) >= 0)
? ? ? ? {
? ? ? ? ? ? outsideRealtimeGuardInterval = false;
? ? ? ? ? ? break;
? ? ? ? }
? ? }
? ? // The task to be invoked
? ? cfTask_t *selectedTask = NULL;
? ? uint16_t selectedTaskDynamicPriority = 0;
? ? // Update task dynamic priorities
? ? uint16_t waitingTasks = 0;
? ? for (cfTask_t *task = queueFirst(); task != NULL; task = queueNext())?
? ? {
? ? ? ? // Task has checkFunc - event driven
? ? ? ? if (task->checkFunc)?
? ? ? ? {
#if defined(SCHEDULER_DEBUG)
? ? ? ? ? ? const timeUs_t currentTimeBeforeCheckFuncCall = micros();
#else
? ? ? ? ? ? const timeUs_t currentTimeBeforeCheckFuncCall = currentTimeUs;
#endif
? ? ? ? ? ? // Increase priority for event driven tasks
? ? ? ? ? ? if (task->dynamicPriority > 0)
? ? ? ? ? ? {
? ? ? ? ? ? ? ? task->taskAgeCycles = 1 + ((currentTimeUs - task->lastSignaledAt) / task->desiredPeriod);
? ? ? ? ? ? ? ? task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles;
? ? ? ? ? ? ? ? waitingTasks++;
? ? ? ? ? ? }?
? ? ? ? ? ? else if (task->checkFunc(currentTimeBeforeCheckFuncCall, currentTimeBeforeCheckFuncCall - task->lastExecutedAt))
? ? ? ? ? ? {
#if defined(SCHEDULER_DEBUG)
? ? ? ? ? ? ? ? DEBUG_SET(DEBUG_SCHEDULER, 3, micros() - currentTimeBeforeCheckFuncCall);
#endif
#ifndef SKIP_TASK_STATISTICS
? ? ? ? ? ? ? ? if (calculateTaskStatistics)?
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? const uint32_t checkFuncExecutionTime = micros() - currentTimeBeforeCheckFuncCall;
? ? ? ? ? ? ? ? ? ? checkFuncMovingSumExecutionTime += checkFuncExecutionTime - checkFuncMovingSumExecutionTime / MOVING_SUM_COUNT;
? ? ? ? ? ? ? ? ? ? checkFuncTotalExecutionTime += checkFuncExecutionTime; ? // time consumed by scheduler + task
? ? ? ? ? ? ? ? ? ? checkFuncMaxExecutionTime = MAX(checkFuncMaxExecutionTime, checkFuncExecutionTime);
? ? ? ? ? ? ? ? }
#endif
? ? ? ? ? ? ? ? task->lastSignaledAt = currentTimeBeforeCheckFuncCall;
? ? ? ? ? ? ? ? task->taskAgeCycles = 1;
? ? ? ? ? ? ? ? task->dynamicPriority = 1 + task->staticPriority;
? ? ? ? ? ? ? ? waitingTasks++;
? ? ? ? ? ? } else?
? ? ? ? ? ? {
? ? ? ? ? ? ? ? task->taskAgeCycles = 0;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? else?
? ? ? ? {
? ? ? ? ? ? // Task is time-driven, dynamicPriority is last execution age (measured in desiredPeriods)
? ? ? ? ? ? // Task age is calculated from last execution
? ? ? ? ? ? task->taskAgeCycles = ((currentTimeUs - task->lastExecutedAt) / task->desiredPeriod);
? ? ? ? ? ? if (task->taskAgeCycles > 0) {
? ? ? ? ? ? ? ? task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles;
? ? ? ? ? ? ? ? waitingTasks++;
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? if (task->dynamicPriority > selectedTaskDynamicPriority) {
? ? ? ? ? ? const bool taskCanBeChosenForScheduling =
? ? ? ? ? ? ? ? (outsideRealtimeGuardInterval) ||
? ? ? ? ? ? ? ? (task->taskAgeCycles > 1) ||
? ? ? ? ? ? ? ? (task->staticPriority == TASK_PRIORITY_REALTIME);
? ? ? ? ? ? if (taskCanBeChosenForScheduling) {
? ? ? ? ? ? ? ? selectedTaskDynamicPriority = task->dynamicPriority;
? ? ? ? ? ? ? ? selectedTask = task;
? ? ? ? ? ? }
? ? ? ? }
? ? }
? ? totalWaitingTasksSamples++;
? ? totalWaitingTasks += waitingTasks;
? ? currentTask = selectedTask;
? ? if (selectedTask)?
? ? {
? ? ? ? // Found a task that should be run
? ? ? ? selectedTask->taskLatestDeltaTime = currentTimeUs - selectedTask->lastExecutedAt;
? ? ? ? selectedTask->lastExecutedAt = currentTimeUs;
? ? ? ? selectedTask->dynamicPriority = 0;
? ? ? ? // Execute task
#ifdef SKIP_TASK_STATISTICS
? ? ? ? selectedTask->taskFunc(currentTimeUs);
#else
? ? ? ? if (calculateTaskStatistics)?
? ? ? ? {
? ? ? ? ? ? const timeUs_t currentTimeBeforeTaskCall = micros();
? ? ? ? ? ? selectedTask->taskFunc(currentTimeBeforeTaskCall);
? ? ? ? ? ? const timeUs_t taskExecutionTime = micros() - currentTimeBeforeTaskCall;
? ? ? ? ? ? selectedTask->movingSumExecutionTime += taskExecutionTime - selectedTask->movingSumExecutionTime / MOVING_SUM_COUNT;
? ? ? ? ? ? selectedTask->totalExecutionTime += taskExecutionTime; ? // time consumed by scheduler + task
? ? ? ? ? ? selectedTask->maxExecutionTime = MAX(selectedTask->maxExecutionTime, taskExecutionTime);
? ? ? ? } else {
? ? ? ? ? ? selectedTask->taskFunc(currentTimeUs);
? ? ? ? }
#endif
#if defined(SCHEDULER_DEBUG)
? ? ? ? DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs - taskExecutionTime); // time spent in scheduler
? ? } else {
? ? ? ? DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs);
#endif
? ? }
? ? GET_SCHEDULER_LOCALS();
}
main函數
int main()
{
systemInit();
fcTasksInit();
? ? while (true) { ??
? ? ? ? scheduler();
}
}
運行效果
/** This file is part of Cleanflight.** Cleanflight is free software: you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation, either version 3 of the License, or* (at your option) any later version.** Cleanflight is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.*/#pragma once #include "stm32f30x.h" #define STATIC_UNIT_TESTED static #define UNUSED(x) (void)(x) #define MIN(a, b) ((a) < (b) ? (a) : (b)) #define MAX(a, b) ((a) > (b) ? (a) : (b)) #define ABS(x) ((x) > 0 ? (x) : -(x)) #define SCHEDULER_DELAY_LIMIT 1 #define GET_SCHEDULER_LOCALS() {} // time difference, 32 bits always sufficienttypedef int32_t timeDelta_t; // millisecond time typedef uint32_t timeMs_t; // microsecond time typedef uint32_t timeUs_t; typedef enum {TASK_PRIORITY_IDLE = 0, // Disables dynamic scheduling, task is executed only if no other task is active this cycleTASK_PRIORITY_LOW = 1,TASK_PRIORITY_MEDIUM = 3,TASK_PRIORITY_MEDIUM_HIGH = 4,TASK_PRIORITY_HIGH = 5,TASK_PRIORITY_REALTIME = 6,TASK_PRIORITY_MAX = 255 } cfTaskPriority_e;typedef struct {timeUs_t maxExecutionTime;timeUs_t totalExecutionTime;timeUs_t averageExecutionTime; } cfCheckFuncInfo_t;typedef struct {const char * taskName;const char * subTaskName;bool isEnabled;uint8_t staticPriority;timeDelta_t desiredPeriod;timeDelta_t latestDeltaTime;timeUs_t maxExecutionTime;timeUs_t totalExecutionTime;timeUs_t averageExecutionTime; } cfTaskInfo_t;typedef enum ActualTasks {/* Actual tasks */TASK_SYSTEM = 0,//TASK_GYROPID,//TASK_ACCEL,//TASK_ATTITUDE,//TASK_RX,TASK_SERIAL,//TASK_DISPATCH,//TASK_BATTERY_VOLTAGE,//TASK_BATTERY_CURRENT,//TASK_BATTERY_ALERTS, #ifdef BEEPERTASK_BEEPER, #endif #ifdef GPSTASK_GPS, #endif #ifdef MAGTASK_COMPASS, #endif #ifdef BAROTASK_BARO, #endif #ifdef SONARTASK_SONAR, #endif #if defined(BARO) || defined(SONAR)TASK_ALTITUDE, #endif #ifdef USE_DASHBOARDTASK_DASHBOARD, #endif #ifdef TELEMETRYTASK_TELEMETRY, #endif #ifdef LED_STRIPTASK_LEDSTRIP, #endif #ifdef TRANSPONDERTASK_TRANSPONDER, #endif #ifdef STACK_CHECKTASK_STACK_CHECK, #endif #ifdef OSDTASK_OSD, #endif #ifdef USE_OSD_SLAVETASK_OSD_SLAVE, #endif #ifdef USE_BSTTASK_BST_MASTER_PROCESS, #endif #ifdef USE_ESC_SENSORTASK_ESC_SENSOR, #endif #ifdef CMSTASK_CMS, #endif #ifdef VTX_CONTROLTASK_VTXCTRL, #endif#ifdef USE_RCSPLITTASK_RCSPLIT, #endif/* Count of real tasks */TASK_COUNT,/* Service task IDs */TASK_NONE = TASK_COUNT,TASK_SELF } cfTaskId_e;typedef struct {// Configurationconst char * taskName;const char * subTaskName;bool (*checkFunc)(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs);void (*taskFunc)(timeUs_t currentTimeUs);timeDelta_t desiredPeriod; // target period of executionconst uint8_t staticPriority; // dynamicPriority grows in steps of this size, shouldn't be zero// Schedulinguint16_t dynamicPriority; // measurement of how old task was last executed, used to avoid task starvationuint16_t taskAgeCycles;timeDelta_t taskLatestDeltaTime;timeUs_t lastExecutedAt; // last time of invocationtimeUs_t lastSignaledAt; // time of invocation event for event-driven tasks#ifndef SKIP_TASK_STATISTICS// StatisticstimeUs_t movingSumExecutionTime; // moving sum over 32 samplestimeUs_t maxExecutionTime;timeUs_t totalExecutionTime; // total time consumed by task since boot #endif } cfTask_t;extern cfTask_t cfTasks[TASK_COUNT]; extern uint16_t averageSystemLoadPercent;void getCheckFuncInfo(cfCheckFuncInfo_t *checkFuncInfo); void getTaskInfo(cfTaskId_e taskId, cfTaskInfo_t *taskInfo); void rescheduleTask(cfTaskId_e taskId, uint32_t newPeriodMicros); void setTaskEnabled(cfTaskId_e taskId, bool newEnabledState); timeDelta_t getTaskDeltaTime(cfTaskId_e taskId); void schedulerSetCalulateTaskStatistics(bool calculateTaskStatistics); void schedulerResetTaskStatistics(cfTaskId_e taskId);void schedulerInit(void); void scheduler(void); void taskSystem(timeUs_t currentTime);#define LOAD_PERCENTAGE_ONE 100#define isSystemOverloaded() (averageSystemLoadPercent >= LOAD_PERCENTAGE_ONE) /** This file is part of Cleanflight.** Cleanflight is free software: you can redistribute it and/or modify* it under the terms of the GNU General Public License as published by* the Free Software Foundation, either version 3 of the License, or* (at your option) any later version.** Cleanflight is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the* GNU General Public License for more details.** You should have received a copy of the GNU General Public License* along with Cleanflight. If not, see <http://www.gnu.org/licenses/>.*/#define SRC_MAIN_SCHEDULER_C_#include <stdbool.h> #include <stdint.h> #include <string.h> #include "scheduler.h" #include "system.h" //#include "platform.h" // //#include "build/build_config.h" //#include "build/debug.h" // //#include "scheduler/scheduler.h" // //#include "config/config_unittest.h" // //#include "common/maths.h" //#include "common/time.h" //#include "common/utils.h" // //#include "drivers/time.h"// DEBUG_SCHEDULER, timings for: // 0 - gyroUpdate() // 1 - pidController() // 2 - time spent in scheduler // 3 - time spent executing check functionstatic cfTask_t *currentTask = NULL;static uint32_t totalWaitingTasks; static uint32_t totalWaitingTasksSamples;static bool calculateTaskStatistics; uint16_t averageSystemLoadPercent = 0;static int taskQueuePos = 0; STATIC_UNIT_TESTED int taskQueueSize = 0;// No need for a linked list for the queue, since items are only inserted at startupSTATIC_UNIT_TESTED cfTask_t* taskQueueArray[TASK_COUNT + 1]; // extra item for NULL pointer at end of queuevoid queueClear(void) {memset(taskQueueArray, 0, sizeof(taskQueueArray));taskQueuePos = 0;taskQueueSize = 0; }bool queueContains(cfTask_t *task) {for (int ii = 0; ii < taskQueueSize; ++ii) {if (taskQueueArray[ii] == task) {return true;}}return false; }bool queueAdd(cfTask_t *task) {if ((taskQueueSize >= TASK_COUNT) || queueContains(task)) {return false;}for (int ii = 0; ii <= taskQueueSize; ++ii) {if (taskQueueArray[ii] == NULL || taskQueueArray[ii]->staticPriority < task->staticPriority) {memmove(&taskQueueArray[ii+1], &taskQueueArray[ii], sizeof(task) * (taskQueueSize - ii));taskQueueArray[ii] = task;++taskQueueSize;return true;}}return false; }bool queueRemove(cfTask_t *task) {for (int ii = 0; ii < taskQueueSize; ++ii) {if (taskQueueArray[ii] == task) {memmove(&taskQueueArray[ii], &taskQueueArray[ii+1], sizeof(task) * (taskQueueSize - ii));--taskQueueSize;return true;}}return false; }/** Returns first item queue or NULL if queue empty*/ cfTask_t *queueFirst(void) {taskQueuePos = 0;return taskQueueArray[0]; // guaranteed to be NULL if queue is empty }/** Returns next item in queue or NULL if at end of queue*/ cfTask_t *queueNext(void) {return taskQueueArray[++taskQueuePos]; // guaranteed to be NULL at end of queue }void taskSystem(timeUs_t currentTimeUs) {UNUSED(currentTimeUs);// Calculate system loadif (totalWaitingTasksSamples > 0) {averageSystemLoadPercent = 100 * totalWaitingTasks / totalWaitingTasksSamples;totalWaitingTasksSamples = 0;totalWaitingTasks = 0;} #if defined(SIMULATOR_BUILD)averageSystemLoadPercent = 0; #endif }#ifndef SKIP_TASK_STATISTICS #define MOVING_SUM_COUNT 32 timeUs_t checkFuncMaxExecutionTime; timeUs_t checkFuncTotalExecutionTime; timeUs_t checkFuncMovingSumExecutionTime;void getCheckFuncInfo(cfCheckFuncInfo_t *checkFuncInfo) {checkFuncInfo->maxExecutionTime = checkFuncMaxExecutionTime;checkFuncInfo->totalExecutionTime = checkFuncTotalExecutionTime;checkFuncInfo->averageExecutionTime = checkFuncMovingSumExecutionTime / MOVING_SUM_COUNT; }void getTaskInfo(cfTaskId_e taskId, cfTaskInfo_t * taskInfo) {taskInfo->taskName = cfTasks[taskId].taskName;taskInfo->subTaskName = cfTasks[taskId].subTaskName;taskInfo->isEnabled = queueContains(&cfTasks[taskId]);taskInfo->desiredPeriod = cfTasks[taskId].desiredPeriod;taskInfo->staticPriority = cfTasks[taskId].staticPriority;taskInfo->maxExecutionTime = cfTasks[taskId].maxExecutionTime;taskInfo->totalExecutionTime = cfTasks[taskId].totalExecutionTime;taskInfo->averageExecutionTime = cfTasks[taskId].movingSumExecutionTime / MOVING_SUM_COUNT;taskInfo->latestDeltaTime = cfTasks[taskId].taskLatestDeltaTime; } #endifvoid rescheduleTask(cfTaskId_e taskId, uint32_t newPeriodMicros) {if (taskId == TASK_SELF) {cfTask_t *task = currentTask;task->desiredPeriod = MAX(SCHEDULER_DELAY_LIMIT, newPeriodMicros); // Limit delay to 100us (10 kHz) to prevent scheduler clogging} else if (taskId < TASK_COUNT) {cfTask_t *task = &cfTasks[taskId];task->desiredPeriod = MAX(SCHEDULER_DELAY_LIMIT, newPeriodMicros); // Limit delay to 100us (10 kHz) to prevent scheduler clogging} }void setTaskEnabled(cfTaskId_e taskId, bool enabled) {if (taskId == TASK_SELF || taskId < TASK_COUNT) {cfTask_t *task = taskId == TASK_SELF ? currentTask : &cfTasks[taskId];if (enabled && task->taskFunc) {queueAdd(task);} else {queueRemove(task);}} }timeDelta_t getTaskDeltaTime(cfTaskId_e taskId) {if (taskId == TASK_SELF) {return currentTask->taskLatestDeltaTime;} else if (taskId < TASK_COUNT) {return cfTasks[taskId].taskLatestDeltaTime;} else {return 0;} }void schedulerSetCalulateTaskStatistics(bool calculateTaskStatisticsToUse) {calculateTaskStatistics = calculateTaskStatisticsToUse; }void schedulerResetTaskStatistics(cfTaskId_e taskId) { #ifdef SKIP_TASK_STATISTICSUNUSED(taskId); #elseif (taskId == TASK_SELF) {currentTask->movingSumExecutionTime = 0;currentTask->totalExecutionTime = 0;currentTask->maxExecutionTime = 0;} else if (taskId < TASK_COUNT) {cfTasks[taskId].movingSumExecutionTime = 0;cfTasks[taskId].totalExecutionTime = 0;cfTasks[taskId].maxExecutionTime = 0;} #endif }void schedulerInit(void) {calculateTaskStatistics = true;queueClear();queueAdd(&cfTasks[TASK_SYSTEM]); }void scheduler(void) {// Cache currentTimeconst timeUs_t currentTimeUs = micros();// Check for realtime tasksbool outsideRealtimeGuardInterval = true;for (const cfTask_t *task = queueFirst(); task != NULL && task->staticPriority >= TASK_PRIORITY_REALTIME; task = queueNext()){const timeUs_t nextExecuteAt = task->lastExecutedAt + task->desiredPeriod;if ((timeDelta_t)(currentTimeUs - nextExecuteAt) >= 0){outsideRealtimeGuardInterval = false;break;}}// The task to be invokedcfTask_t *selectedTask = NULL;uint16_t selectedTaskDynamicPriority = 0;// Update task dynamic prioritiesuint16_t waitingTasks = 0;for (cfTask_t *task = queueFirst(); task != NULL; task = queueNext()) {// Task has checkFunc - event drivenif (task->checkFunc) { #if defined(SCHEDULER_DEBUG)const timeUs_t currentTimeBeforeCheckFuncCall = micros(); #elseconst timeUs_t currentTimeBeforeCheckFuncCall = currentTimeUs; #endif// Increase priority for event driven tasksif (task->dynamicPriority > 0){task->taskAgeCycles = 1 + ((currentTimeUs - task->lastSignaledAt) / task->desiredPeriod);task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles;waitingTasks++;} else if (task->checkFunc(currentTimeBeforeCheckFuncCall, currentTimeBeforeCheckFuncCall - task->lastExecutedAt)){ #if defined(SCHEDULER_DEBUG)DEBUG_SET(DEBUG_SCHEDULER, 3, micros() - currentTimeBeforeCheckFuncCall); #endif #ifndef SKIP_TASK_STATISTICSif (calculateTaskStatistics) {const uint32_t checkFuncExecutionTime = micros() - currentTimeBeforeCheckFuncCall;checkFuncMovingSumExecutionTime += checkFuncExecutionTime - checkFuncMovingSumExecutionTime / MOVING_SUM_COUNT;checkFuncTotalExecutionTime += checkFuncExecutionTime; // time consumed by scheduler + taskcheckFuncMaxExecutionTime = MAX(checkFuncMaxExecutionTime, checkFuncExecutionTime);} #endiftask->lastSignaledAt = currentTimeBeforeCheckFuncCall;task->taskAgeCycles = 1;task->dynamicPriority = 1 + task->staticPriority;waitingTasks++;} else {task->taskAgeCycles = 0;}}else {// Task is time-driven, dynamicPriority is last execution age (measured in desiredPeriods)// Task age is calculated from last executiontask->taskAgeCycles = ((currentTimeUs - task->lastExecutedAt) / task->desiredPeriod);if (task->taskAgeCycles > 0) {task->dynamicPriority = 1 + task->staticPriority * task->taskAgeCycles;waitingTasks++;}}if (task->dynamicPriority > selectedTaskDynamicPriority) {const bool taskCanBeChosenForScheduling =(outsideRealtimeGuardInterval) ||(task->taskAgeCycles > 1) ||(task->staticPriority == TASK_PRIORITY_REALTIME);if (taskCanBeChosenForScheduling) {selectedTaskDynamicPriority = task->dynamicPriority;selectedTask = task;}}}totalWaitingTasksSamples++;totalWaitingTasks += waitingTasks;currentTask = selectedTask;if (selectedTask) {// Found a task that should be runselectedTask->taskLatestDeltaTime = currentTimeUs - selectedTask->lastExecutedAt;selectedTask->lastExecutedAt = currentTimeUs;selectedTask->dynamicPriority = 0;// Execute task #ifdef SKIP_TASK_STATISTICSselectedTask->taskFunc(currentTimeUs); #elseif (calculateTaskStatistics) {const timeUs_t currentTimeBeforeTaskCall = micros();selectedTask->taskFunc(currentTimeBeforeTaskCall);const timeUs_t taskExecutionTime = micros() - currentTimeBeforeTaskCall;selectedTask->movingSumExecutionTime += taskExecutionTime - selectedTask->movingSumExecutionTime / MOVING_SUM_COUNT;selectedTask->totalExecutionTime += taskExecutionTime; // time consumed by scheduler + taskselectedTask->maxExecutionTime = MAX(selectedTask->maxExecutionTime, taskExecutionTime);} else {selectedTask->taskFunc(currentTimeUs);}#endif #if defined(SCHEDULER_DEBUG)DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs - taskExecutionTime); // time spent in scheduler} else {DEBUG_SET(DEBUG_SCHEDULER, 2, micros() - currentTimeUs); #endif}GET_SCHEDULER_LOCALS(); }?
?
總結
以上是生活随笔為你收集整理的CleanFlight 源码分析 一,任务调度的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 手机玩王者荣耀死机是怎么回事
- 下一篇: wps怎么选中一部分(Download)