1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-24 16:55:36 +03:00
betaflight/src/main/scheduler/scheduler.h

233 lines
6.8 KiB
C

/*
* This file is part of Cleanflight and Betaflight.
*
* Cleanflight and Betaflight are free software. You can redistribute
* this software and/or modify this software 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 and Betaflight are distributed in the hope that they
* 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 this software.
*
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/time.h"
#include "config/config.h"
#define TASK_PERIOD_HZ(hz) (1000000 / (hz))
#define TASK_PERIOD_MS(ms) ((ms) * 1000)
#define TASK_PERIOD_US(us) (us)
#define TASK_STATS_MOVING_SUM_COUNT 32
#define LOAD_PERCENTAGE_ONE 100
#define SCHED_START_LOOP_MIN_US 4 // Wait at start of scheduler loop if gyroTask is nearly due
#define SCHED_START_LOOP_MAX_US 12
#define SCHED_START_LOOP_DOWN_STEP 50 // Fraction of a us to reduce start loop wait
#define SCHED_START_LOOP_UP_STEP 1 // Fraction of a us to increase start loop wait
#define TASK_GUARD_MARGIN_MIN_US 3 // Add an amount to the estimate of a task duration
#define TASK_GUARD_MARGIN_MAX_US 5
#define TASK_GUARD_MARGIN_DOWN_STEP 50 // Fraction of a us to reduce task guard margin
#define TASK_GUARD_MARGIN_UP_STEP 1 // Fraction of a us to increase task guard margin
#define CHECK_GUARD_MARGIN_US 2 // Add a margin to the amount of time allowed for a check function to run
#define TASK_AGE_EXPEDITE_COUNT 1 // Make aged tasks more schedulable
#define TASK_AGE_EXPEDITE_SCALE 0.9 // By scaling their expected execution time
// Gyro interrupt counts over which to measure loop time and skew
#define GYRO_RATE_COUNT 25000
#define GYRO_LOCK_COUNT 400
typedef enum {
TASK_PRIORITY_REALTIME = -1, // Task will be run outside the scheduler logic
TASK_PRIORITY_IDLE = 0, // Disables dynamic scheduling, task is executed only if no other task is active this cycle
TASK_PRIORITY_LOW = 1,
TASK_PRIORITY_MEDIUM = 3,
TASK_PRIORITY_MEDIUM_HIGH = 4,
TASK_PRIORITY_HIGH = 5,
TASK_PRIORITY_MAX = 255
} taskPriority_e;
typedef struct {
timeUs_t maxExecutionTimeUs;
timeUs_t totalExecutionTimeUs;
timeUs_t averageExecutionTimeUs;
timeUs_t averageDeltaTimeUs;
} cfCheckFuncInfo_t;
typedef struct {
const char * taskName;
const char * subTaskName;
bool isEnabled;
int8_t staticPriority;
timeDelta_t desiredPeriodUs;
timeDelta_t latestDeltaTimeUs;
timeUs_t maxExecutionTimeUs;
timeUs_t totalExecutionTimeUs;
timeUs_t averageExecutionTimeUs;
timeUs_t averageDeltaTimeUs;
float movingAverageCycleTimeUs;
#if defined(USE_LATE_TASK_STATISTICS)
uint32_t runCount;
uint32_t lateCount;
timeUs_t execTime;
#endif
} taskInfo_t;
typedef enum {
/* Actual tasks */
TASK_SYSTEM = 0,
TASK_MAIN,
TASK_GYRO,
TASK_FILTER,
TASK_PID,
TASK_ACCEL,
TASK_ATTITUDE,
TASK_RX,
TASK_SERIAL,
TASK_DISPATCH,
TASK_BATTERY_VOLTAGE,
TASK_BATTERY_CURRENT,
TASK_BATTERY_ALERTS,
#ifdef USE_BEEPER
TASK_BEEPER,
#endif
#ifdef USE_GPS
TASK_GPS,
#endif
#ifdef USE_MAG
TASK_COMPASS,
#endif
#ifdef USE_BARO
TASK_BARO,
#endif
#ifdef USE_RANGEFINDER
TASK_RANGEFINDER,
#endif
#if defined(USE_BARO) || defined(USE_GPS)
TASK_ALTITUDE,
#endif
#ifdef USE_DASHBOARD
TASK_DASHBOARD,
#endif
#ifdef USE_TELEMETRY
TASK_TELEMETRY,
#endif
#ifdef USE_LED_STRIP
TASK_LEDSTRIP,
#endif
#ifdef USE_TRANSPONDER
TASK_TRANSPONDER,
#endif
#ifdef USE_STACK_CHECK
TASK_STACK_CHECK,
#endif
#ifdef USE_OSD
TASK_OSD,
#endif
#ifdef USE_BST
TASK_BST_MASTER_PROCESS,
#endif
#ifdef USE_ESC_SENSOR
TASK_ESC_SENSOR,
#endif
#ifdef USE_CMS
TASK_CMS,
#endif
#ifdef USE_VTX_CONTROL
TASK_VTXCTRL,
#endif
#ifdef USE_CAMERA_CONTROL
TASK_CAMCTRL,
#endif
#ifdef USE_RCDEVICE
TASK_RCDEVICE,
#endif
#ifdef USE_ADC_INTERNAL
TASK_ADC_INTERNAL,
#endif
#ifdef USE_PINIOBOX
TASK_PINIOBOX,
#endif
#ifdef USE_CRSF_V3
TASK_SPEED_NEGOTIATION,
#endif
/* Count of real tasks */
TASK_COUNT,
/* Service task IDs */
TASK_NONE = TASK_COUNT,
TASK_SELF
} taskId_e;
typedef struct {
// Configuration
const char * taskName;
const char * subTaskName;
bool (*checkFunc)(timeUs_t currentTimeUs, timeDelta_t currentDeltaTimeUs);
void (*taskFunc)(timeUs_t currentTimeUs);
timeDelta_t desiredPeriodUs; // target period of execution
const int8_t staticPriority; // dynamicPriority grows in steps of this size
// Scheduling
uint16_t dynamicPriority; // measurement of how old task was last executed, used to avoid task starvation
uint16_t taskAgeCycles;
timeDelta_t taskLatestDeltaTimeUs;
timeUs_t lastExecutedAtUs; // last time of invocation
timeUs_t lastSignaledAtUs; // time of invocation event for event-driven tasks
timeUs_t lastDesiredAt; // time of last desired execution
// Statistics
float movingAverageCycleTimeUs;
timeUs_t anticipatedExecutionTimeUs; // moving sum over 32 samples
timeUs_t movingSumDeltaTimeUs; // moving sum over 32 samples
timeUs_t maxExecutionTimeUs;
timeUs_t totalExecutionTimeUs; // total time consumed by task since boot
timeUs_t lastStatsAtUs; // time of last stats gathering for rate calculation
#if defined(USE_LATE_TASK_STATISTICS)
uint32_t runCount;
uint32_t lateCount;
timeUs_t execTime;
#endif
} task_t;
void getCheckFuncInfo(cfCheckFuncInfo_t *checkFuncInfo);
void getTaskInfo(taskId_e taskId, taskInfo_t *taskInfo);
void rescheduleTask(taskId_e taskId, timeDelta_t newPeriodUs);
void setTaskEnabled(taskId_e taskId, bool newEnabledState);
timeDelta_t getTaskDeltaTimeUs(taskId_e taskId);
void ignoreTaskStateTime();
void ignoreTaskExecRate();
void ignoreTaskExecTime();
bool getIgnoreTaskExecTime();
void schedulerResetTaskStatistics(taskId_e taskId);
void schedulerResetTaskMaxExecutionTime(taskId_e taskId);
void schedulerResetCheckFunctionMaxExecutionTime(void);
void schedulerSetNextStateTime(timeDelta_t nextStateTime);
void schedulerInit(void);
void scheduler(void);
timeUs_t schedulerExecuteTask(task_t *selectedTask, timeUs_t currentTimeUs);
void taskSystemLoad(timeUs_t currentTimeUs);
void schedulerOptimizeRate(bool optimizeRate);
void schedulerEnableGyro(void);
uint16_t getAverageSystemLoadPercent(void);
float schedulerGetCycleTimeMultiplier(void);