2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
23 #include "common/time.h"
24 #include "config/config.h"
25 #include "pg/scheduler.h"
27 #define TASK_PERIOD_HZ(hz) (1000000 / (hz))
28 #define TASK_PERIOD_MS(ms) ((ms) * 1000)
29 #define TASK_PERIOD_US(us) (us)
31 #define TASK_STATS_MOVING_SUM_COUNT 8
33 #define LOAD_PERCENTAGE_ONE 100
35 #define SCHED_TASK_DEFER_MASK 0x07 // Scheduler loop count is masked with this and when 0 long running tasks are processed
37 #define SCHED_START_LOOP_MIN_US 1 // Wait at start of scheduler loop if gyroTask is nearly due
38 #define SCHED_START_LOOP_MAX_US 12
39 #define SCHED_START_LOOP_DOWN_STEP 50 // Fraction of a us to reduce start loop wait
40 #define SCHED_START_LOOP_UP_STEP 1 // Fraction of a us to increase start loop wait
42 #define TASK_GUARD_MARGIN_MIN_US 3 // Add an amount to the estimate of a task duration
43 #define TASK_GUARD_MARGIN_MAX_US 6
44 #define TASK_GUARD_MARGIN_DOWN_STEP 50 // Fraction of a us to reduce task guard margin
45 #define TASK_GUARD_MARGIN_UP_STEP 1 // Fraction of a us to increase task guard margin
47 #define CHECK_GUARD_MARGIN_US 2 // Add a margin to the amount of time allowed for a check function to run
49 // Some tasks have occasional peaks in execution time so normal moving average duration estimation doesn't work
50 // Decay the estimated max task duration by 1/(1 << TASK_EXEC_TIME_SHIFT) on every invocation
51 #define TASK_EXEC_TIME_SHIFT 7
53 #define TASK_AGE_EXPEDITE_RX schedulerConfig()->rxRelaxDeterminism // Make RX tasks more schedulable if it's failed to be scheduled this many times
54 #define TASK_AGE_EXPEDITE_OSD schedulerConfig()->osdRelaxDeterminism // Make OSD tasks more schedulable if it's failed to be scheduled this many times
55 #define TASK_AGE_EXPEDITE_COUNT 1 // Make aged tasks more schedulable
56 #define TASK_AGE_EXPEDITE_SCALE 0.9 // By scaling their expected execution time
58 // Gyro interrupt counts over which to measure loop time and skew
59 #define GYRO_RATE_COUNT 25000
60 #define GYRO_LOCK_COUNT 50
63 TASK_PRIORITY_REALTIME
= -1, // Task will be run outside the scheduler logic
64 TASK_PRIORITY_LOWEST
= 1,
65 TASK_PRIORITY_LOW
= 2,
66 TASK_PRIORITY_MEDIUM
= 3,
67 TASK_PRIORITY_MEDIUM_HIGH
= 4,
68 TASK_PRIORITY_HIGH
= 5,
69 TASK_PRIORITY_MAX
= 255
73 timeUs_t maxExecutionTimeUs
;
74 timeUs_t totalExecutionTimeUs
;
75 timeUs_t averageExecutionTimeUs
;
76 timeUs_t averageDeltaTimeUs
;
80 const char * taskName
;
81 const char * subTaskName
;
83 int8_t staticPriority
;
84 timeDelta_t desiredPeriodUs
;
85 timeDelta_t latestDeltaTimeUs
;
86 timeUs_t maxExecutionTimeUs
;
87 timeUs_t totalExecutionTimeUs
;
88 timeUs_t averageExecutionTime10thUs
;
89 timeUs_t averageDeltaTime10thUs
;
90 float movingAverageCycleTimeUs
;
91 #if defined(USE_LATE_TASK_STATISTICS)
110 TASK_BATTERY_VOLTAGE
,
111 TASK_BATTERY_CURRENT
,
119 #ifdef USE_GPS_RESCUE
128 #ifdef USE_RANGEFINDER
131 #if defined(USE_BARO) || defined(USE_GPS)
143 #ifdef USE_TRANSPONDER
146 #ifdef USE_STACK_CHECK
153 TASK_BST_MASTER_PROCESS
,
155 #ifdef USE_ESC_SENSOR
161 #ifdef USE_VTX_CONTROL
164 #ifdef USE_CAMERA_CONTROL
170 #ifdef USE_ADC_INTERNAL
177 TASK_SPEED_NEGOTIATION
,
180 /* Count of real tasks */
183 /* Service task IDs */
184 TASK_NONE
= TASK_COUNT
,
190 const char * taskName
;
191 const char * subTaskName
;
192 bool (*checkFunc
)(timeUs_t currentTimeUs
, timeDelta_t currentDeltaTimeUs
);
193 void (*taskFunc
)(timeUs_t currentTimeUs
);
194 timeDelta_t desiredPeriodUs
; // target period of execution
195 const int8_t staticPriority
; // dynamicPriority grows in steps of this size
200 task_attribute_t
*attribute
;
203 uint16_t dynamicPriority
; // measurement of how old task was last executed, used to avoid task starvation
204 uint16_t taskAgePeriods
;
205 timeDelta_t taskLatestDeltaTimeUs
;
206 timeUs_t lastExecutedAtUs
; // last time of invocation
207 timeUs_t lastSignaledAtUs
; // time of invocation event for event-driven tasks
208 timeUs_t lastDesiredAt
; // time of last desired execution
211 float movingAverageCycleTimeUs
;
212 timeUs_t anticipatedExecutionTime
; // Fixed point expectation of next execution time
213 timeUs_t movingSumDeltaTime10thUs
; // moving sum over 64 samples
214 timeUs_t movingSumExecutionTime10thUs
;
215 timeUs_t maxExecutionTimeUs
;
216 timeUs_t totalExecutionTimeUs
; // total time consumed by task since boot
217 timeUs_t lastStatsAtUs
; // time of last stats gathering for rate calculation
218 #if defined(USE_LATE_TASK_STATISTICS)
225 void getCheckFuncInfo(cfCheckFuncInfo_t
*checkFuncInfo
);
226 void getTaskInfo(taskId_e taskId
, taskInfo_t
*taskInfo
);
227 void rescheduleTask(taskId_e taskId
, timeDelta_t newPeriodUs
);
228 void setTaskEnabled(taskId_e taskId
, bool newEnabledState
);
229 timeDelta_t
getTaskDeltaTimeUs(taskId_e taskId
);
230 void schedulerIgnoreTaskStateTime();
231 void schedulerIgnoreTaskExecRate();
232 void schedulerIgnoreTaskExecTime();
233 bool schedulerGetIgnoreTaskExecTime();
234 void schedulerResetTaskStatistics(taskId_e taskId
);
235 void schedulerResetTaskMaxExecutionTime(taskId_e taskId
);
236 void schedulerResetCheckFunctionMaxExecutionTime(void);
237 void schedulerSetNextStateTime(timeDelta_t nextStateTime
);
238 timeDelta_t
schedulerGetNextStateTime(void);
239 void schedulerInit(void);
240 void scheduler(void);
241 timeUs_t
schedulerExecuteTask(task_t
*selectedTask
, timeUs_t currentTimeUs
);
242 void taskSystemLoad(timeUs_t currentTimeUs
);
243 void schedulerEnableGyro(void);
244 uint16_t getAverageSystemLoadPercent(void);
245 float schedulerGetCycleTimeMultiplier(void);