Split initialised/non-initialised task data
[betaflight.git] / src / main / scheduler / scheduler.h
blobaeca0478e5ac4a6189d41b461c3c3dda64d7914f
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"
26 #define TASK_PERIOD_HZ(hz) (1000000 / (hz))
27 #define TASK_PERIOD_MS(ms) ((ms) * 1000)
28 #define TASK_PERIOD_US(us) (us)
30 #define TASK_STATS_MOVING_SUM_COUNT 64
32 #define LOAD_PERCENTAGE_ONE 100
34 #define SCHED_START_LOOP_MIN_US 1 // Wait at start of scheduler loop if gyroTask is nearly due
35 #define SCHED_START_LOOP_MAX_US 12
36 #define SCHED_START_LOOP_DOWN_STEP 50 // Fraction of a us to reduce start loop wait
37 #define SCHED_START_LOOP_UP_STEP 1 // Fraction of a us to increase start loop wait
39 #define TASK_GUARD_MARGIN_MIN_US 3 // Add an amount to the estimate of a task duration
40 #define TASK_GUARD_MARGIN_MAX_US 6
41 #define TASK_GUARD_MARGIN_DOWN_STEP 50 // Fraction of a us to reduce task guard margin
42 #define TASK_GUARD_MARGIN_UP_STEP 1 // Fraction of a us to increase task guard margin
44 #define CHECK_GUARD_MARGIN_US 2 // Add a margin to the amount of time allowed for a check function to run
46 // Some tasks have occasional peaks in execution time so normal moving average duration estimation doesn't work
47 // Decay the estimated max task duration by 1/(1 << TASK_EXEC_TIME_SHIFT) on every invocation
48 #define TASK_EXEC_TIME_SHIFT 7
50 #define TASK_AGE_EXPEDITE_COUNT 1 // Make aged tasks more schedulable
51 #define TASK_AGE_EXPEDITE_SCALE 0.9 // By scaling their expected execution time
53 // Gyro interrupt counts over which to measure loop time and skew
54 #define GYRO_RATE_COUNT 25000
55 #define GYRO_LOCK_COUNT 400
57 typedef enum {
58 TASK_PRIORITY_REALTIME = -1, // Task will be run outside the scheduler logic
59 TASK_PRIORITY_IDLE = 0, // Disables dynamic scheduling, task is executed only if no other task is active this cycle
60 TASK_PRIORITY_LOW = 1,
61 TASK_PRIORITY_MEDIUM = 3,
62 TASK_PRIORITY_MEDIUM_HIGH = 4,
63 TASK_PRIORITY_HIGH = 5,
64 TASK_PRIORITY_MAX = 255
65 } taskPriority_e;
67 typedef struct {
68 timeUs_t maxExecutionTimeUs;
69 timeUs_t totalExecutionTimeUs;
70 timeUs_t averageExecutionTimeUs;
71 timeUs_t averageDeltaTimeUs;
72 } cfCheckFuncInfo_t;
74 typedef struct {
75 const char * taskName;
76 const char * subTaskName;
77 bool isEnabled;
78 int8_t staticPriority;
79 timeDelta_t desiredPeriodUs;
80 timeDelta_t latestDeltaTimeUs;
81 timeUs_t maxExecutionTimeUs;
82 timeUs_t totalExecutionTimeUs;
83 timeUs_t averageExecutionTimeUs;
84 timeUs_t averageDeltaTime10thUs;
85 float movingAverageCycleTimeUs;
86 #if defined(USE_LATE_TASK_STATISTICS)
87 uint32_t runCount;
88 uint32_t lateCount;
89 timeUs_t execTime;
90 #endif
91 } taskInfo_t;
93 typedef enum {
94 /* Actual tasks */
95 TASK_SYSTEM = 0,
96 TASK_MAIN,
97 TASK_GYRO,
98 TASK_FILTER,
99 TASK_PID,
100 TASK_ACCEL,
101 TASK_ATTITUDE,
102 TASK_RX,
103 TASK_SERIAL,
104 TASK_DISPATCH,
105 TASK_BATTERY_VOLTAGE,
106 TASK_BATTERY_CURRENT,
107 TASK_BATTERY_ALERTS,
108 #ifdef USE_BEEPER
109 TASK_BEEPER,
110 #endif
111 #ifdef USE_GPS
112 TASK_GPS,
113 #endif
114 #ifdef USE_MAG
115 TASK_COMPASS,
116 #endif
117 #ifdef USE_BARO
118 TASK_BARO,
119 #endif
120 #ifdef USE_RANGEFINDER
121 TASK_RANGEFINDER,
122 #endif
123 #if defined(USE_BARO) || defined(USE_GPS)
124 TASK_ALTITUDE,
125 #endif
126 #ifdef USE_DASHBOARD
127 TASK_DASHBOARD,
128 #endif
129 #ifdef USE_TELEMETRY
130 TASK_TELEMETRY,
131 #endif
132 #ifdef USE_LED_STRIP
133 TASK_LEDSTRIP,
134 #endif
135 #ifdef USE_TRANSPONDER
136 TASK_TRANSPONDER,
137 #endif
138 #ifdef USE_STACK_CHECK
139 TASK_STACK_CHECK,
140 #endif
141 #ifdef USE_OSD
142 TASK_OSD,
143 #endif
144 #ifdef USE_BST
145 TASK_BST_MASTER_PROCESS,
146 #endif
147 #ifdef USE_ESC_SENSOR
148 TASK_ESC_SENSOR,
149 #endif
150 #ifdef USE_CMS
151 TASK_CMS,
152 #endif
153 #ifdef USE_VTX_CONTROL
154 TASK_VTXCTRL,
155 #endif
156 #ifdef USE_CAMERA_CONTROL
157 TASK_CAMCTRL,
158 #endif
160 #ifdef USE_RCDEVICE
161 TASK_RCDEVICE,
162 #endif
164 #ifdef USE_ADC_INTERNAL
165 TASK_ADC_INTERNAL,
166 #endif
168 #ifdef USE_PINIOBOX
169 TASK_PINIOBOX,
170 #endif
172 #ifdef USE_CRSF_V3
173 TASK_SPEED_NEGOTIATION,
174 #endif
176 /* Count of real tasks */
177 TASK_COUNT,
179 /* Service task IDs */
180 TASK_NONE = TASK_COUNT,
181 TASK_SELF
182 } taskId_e;
184 typedef struct {
185 // Configuration
186 const char * taskName;
187 const char * subTaskName;
188 bool (*checkFunc)(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs);
189 void (*taskFunc)(timeUs_t currentTimeUs);
190 timeDelta_t desiredPeriodUs; // target period of execution
191 const int8_t staticPriority; // dynamicPriority grows in steps of this size
192 } task_id_t;
194 typedef struct {
195 // Task static data
196 task_id_t *id;
198 // Scheduling
199 uint16_t dynamicPriority; // measurement of how old task was last executed, used to avoid task starvation
200 uint16_t taskAgeCycles;
201 timeDelta_t taskLatestDeltaTimeUs;
202 timeUs_t lastExecutedAtUs; // last time of invocation
203 timeUs_t lastSignaledAtUs; // time of invocation event for event-driven tasks
204 timeUs_t lastDesiredAt; // time of last desired execution
206 // Statistics
207 float movingAverageCycleTimeUs;
208 timeUs_t anticipatedExecutionTime; // Fixed point expectation of next execution time
209 timeUs_t movingSumDeltaTime10thUs; // moving sum over 64 samples
210 timeUs_t maxExecutionTimeUs;
211 timeUs_t totalExecutionTimeUs; // total time consumed by task since boot
212 timeUs_t lastStatsAtUs; // time of last stats gathering for rate calculation
213 #if defined(USE_LATE_TASK_STATISTICS)
214 uint32_t runCount;
215 uint32_t lateCount;
216 timeUs_t execTime;
217 #endif
218 } task_t;
220 void getCheckFuncInfo(cfCheckFuncInfo_t *checkFuncInfo);
221 void getTaskInfo(taskId_e taskId, taskInfo_t *taskInfo);
222 void rescheduleTask(taskId_e taskId, timeDelta_t newPeriodUs);
223 void setTaskEnabled(taskId_e taskId, bool newEnabledState);
224 timeDelta_t getTaskDeltaTimeUs(taskId_e taskId);
225 void schedulerIgnoreTaskStateTime();
226 void schedulerIgnoreTaskExecRate();
227 void schedulerIgnoreTaskExecTime();
228 bool schedulerGetIgnoreTaskExecTime();
229 void schedulerResetTaskStatistics(taskId_e taskId);
230 void schedulerResetTaskMaxExecutionTime(taskId_e taskId);
231 void schedulerResetCheckFunctionMaxExecutionTime(void);
232 void schedulerSetNextStateTime(timeDelta_t nextStateTime);
233 void schedulerInit(void);
234 void scheduler(void);
235 timeUs_t schedulerExecuteTask(task_t *selectedTask, timeUs_t currentTimeUs);
236 void taskSystemLoad(timeUs_t currentTimeUs);
237 void schedulerEnableGyro(void);
238 uint16_t getAverageSystemLoadPercent(void);
239 float schedulerGetCycleTimeMultiplier(void);