Merge pull request #11483 from SteveCEvans/elrs_race
[betaflight.git] / src / main / scheduler / scheduler.h
bloba9cb63db7357b5bce240532d0aa9b2e6a04ad0ab
1 /*
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)
8 * any later version.
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/>.
21 #pragma once
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
62 typedef enum {
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
70 } taskPriority_e;
72 typedef struct {
73 timeUs_t maxExecutionTimeUs;
74 timeUs_t totalExecutionTimeUs;
75 timeUs_t averageExecutionTimeUs;
76 timeUs_t averageDeltaTimeUs;
77 } cfCheckFuncInfo_t;
79 typedef struct {
80 const char * taskName;
81 const char * subTaskName;
82 bool isEnabled;
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)
92 uint32_t runCount;
93 uint32_t lateCount;
94 timeUs_t execTime;
95 #endif
96 } taskInfo_t;
98 typedef enum {
99 /* Actual tasks */
100 TASK_SYSTEM = 0,
101 TASK_MAIN,
102 TASK_GYRO,
103 TASK_FILTER,
104 TASK_PID,
105 TASK_ACCEL,
106 TASK_ATTITUDE,
107 TASK_RX,
108 TASK_SERIAL,
109 TASK_DISPATCH,
110 TASK_BATTERY_VOLTAGE,
111 TASK_BATTERY_CURRENT,
112 TASK_BATTERY_ALERTS,
113 #ifdef USE_BEEPER
114 TASK_BEEPER,
115 #endif
116 #ifdef USE_GPS
117 TASK_GPS,
118 #endif
119 #ifdef USE_MAG
120 TASK_COMPASS,
121 #endif
122 #ifdef USE_BARO
123 TASK_BARO,
124 #endif
125 #ifdef USE_RANGEFINDER
126 TASK_RANGEFINDER,
127 #endif
128 #if defined(USE_BARO) || defined(USE_GPS)
129 TASK_ALTITUDE,
130 #endif
131 #ifdef USE_DASHBOARD
132 TASK_DASHBOARD,
133 #endif
134 #ifdef USE_TELEMETRY
135 TASK_TELEMETRY,
136 #endif
137 #ifdef USE_LED_STRIP
138 TASK_LEDSTRIP,
139 #endif
140 #ifdef USE_TRANSPONDER
141 TASK_TRANSPONDER,
142 #endif
143 #ifdef USE_STACK_CHECK
144 TASK_STACK_CHECK,
145 #endif
146 #ifdef USE_OSD
147 TASK_OSD,
148 #endif
149 #ifdef USE_BST
150 TASK_BST_MASTER_PROCESS,
151 #endif
152 #ifdef USE_ESC_SENSOR
153 TASK_ESC_SENSOR,
154 #endif
155 #ifdef USE_CMS
156 TASK_CMS,
157 #endif
158 #ifdef USE_VTX_CONTROL
159 TASK_VTXCTRL,
160 #endif
161 #ifdef USE_CAMERA_CONTROL
162 TASK_CAMCTRL,
163 #endif
165 #ifdef USE_RCDEVICE
166 TASK_RCDEVICE,
167 #endif
169 #ifdef USE_ADC_INTERNAL
170 TASK_ADC_INTERNAL,
171 #endif
173 #ifdef USE_PINIOBOX
174 TASK_PINIOBOX,
175 #endif
177 #ifdef USE_CRSF_V3
178 TASK_SPEED_NEGOTIATION,
179 #endif
181 /* Count of real tasks */
182 TASK_COUNT,
184 /* Service task IDs */
185 TASK_NONE = TASK_COUNT,
186 TASK_SELF
187 } taskId_e;
189 typedef struct {
190 // Configuration
191 const char * taskName;
192 const char * subTaskName;
193 bool (*checkFunc)(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs);
194 void (*taskFunc)(timeUs_t currentTimeUs);
195 timeDelta_t desiredPeriodUs; // target period of execution
196 const int8_t staticPriority; // dynamicPriority grows in steps of this size
197 } task_attribute_t;
199 typedef struct {
200 // Task static data
201 task_attribute_t *attribute;
203 // Scheduling
204 uint16_t dynamicPriority; // measurement of how old task was last executed, used to avoid task starvation
205 uint16_t taskAgePeriods;
206 timeDelta_t taskLatestDeltaTimeUs;
207 timeUs_t lastExecutedAtUs; // last time of invocation
208 timeUs_t lastSignaledAtUs; // time of invocation event for event-driven tasks
209 timeUs_t lastDesiredAt; // time of last desired execution
211 // Statistics
212 float movingAverageCycleTimeUs;
213 timeUs_t anticipatedExecutionTime; // Fixed point expectation of next execution time
214 timeUs_t movingSumDeltaTime10thUs; // moving sum over 64 samples
215 timeUs_t movingSumExecutionTime10thUs;
216 timeUs_t maxExecutionTimeUs;
217 timeUs_t totalExecutionTimeUs; // total time consumed by task since boot
218 timeUs_t lastStatsAtUs; // time of last stats gathering for rate calculation
219 #if defined(USE_LATE_TASK_STATISTICS)
220 uint32_t runCount;
221 uint32_t lateCount;
222 timeUs_t execTime;
223 #endif
224 } task_t;
226 void getCheckFuncInfo(cfCheckFuncInfo_t *checkFuncInfo);
227 void getTaskInfo(taskId_e taskId, taskInfo_t *taskInfo);
228 void rescheduleTask(taskId_e taskId, timeDelta_t newPeriodUs);
229 void setTaskEnabled(taskId_e taskId, bool newEnabledState);
230 timeDelta_t getTaskDeltaTimeUs(taskId_e taskId);
231 void schedulerIgnoreTaskStateTime();
232 void schedulerIgnoreTaskExecRate();
233 void schedulerIgnoreTaskExecTime();
234 bool schedulerGetIgnoreTaskExecTime();
235 void schedulerResetTaskStatistics(taskId_e taskId);
236 void schedulerResetTaskMaxExecutionTime(taskId_e taskId);
237 void schedulerResetCheckFunctionMaxExecutionTime(void);
238 void schedulerSetNextStateTime(timeDelta_t nextStateTime);
239 timeDelta_t schedulerGetNextStateTime();
240 void schedulerInit(void);
241 void scheduler(void);
242 timeUs_t schedulerExecuteTask(task_t *selectedTask, timeUs_t currentTimeUs);
243 void taskSystemLoad(timeUs_t currentTimeUs);
244 void schedulerEnableGyro(void);
245 uint16_t getAverageSystemLoadPercent(void);
246 float schedulerGetCycleTimeMultiplier(void);