From 29d221502e0b789225f044cd5e3967462f9faa43 Mon Sep 17 00:00:00 2001 From: Steve Evans Date: Fri, 14 Aug 2020 16:42:20 +0100 Subject: [PATCH 1/2] Use peak tracking as default for task duration estimation rather than a moving average --- src/main/cli/settings.c | 1 - src/main/config/config.c | 6 ++-- src/main/config/config.h | 7 ---- src/main/drivers/light_ws2811strip.c | 2 +- src/main/fc/dispatch.c | 6 ++-- src/main/fc/tasks.c | 28 +++++++-------- src/main/flight/imu.c | 2 +- src/main/flight/position.c | 2 +- src/main/io/beeper.c | 3 ++ src/main/io/ledstrip.c | 14 ++++---- src/main/msp/msp.c | 2 +- src/main/osd/osd.c | 16 +++++---- src/main/scheduler/scheduler.c | 38 ++++++++++++--------- src/main/scheduler/scheduler.h | 23 +++++++------ src/main/sensors/barometer.c | 8 ++--- src/main/sensors/battery.c | 4 +-- src/test/unit/arming_prevention_unittest.cc | 1 + src/test/unit/flight_imu_unittest.cc | 6 ++-- src/test/unit/ledstrip_unittest.cc | 4 ++- src/test/unit/link_quality_unittest.cc | 6 ++-- src/test/unit/osd_unittest.cc | 6 ++-- src/test/unit/vtx_unittest.cc | 2 +- src/test/unit/ws2811_unittest.cc | 4 +-- 23 files changed, 100 insertions(+), 91 deletions(-) diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index c9e560364e..d18494b9ef 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -1477,7 +1477,6 @@ const clivalue_t valueTable[] = { { "cpu_overclock", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OVERCLOCK }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, cpu_overclock) }, #endif { "pwr_on_arm_grace", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 30 }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, powerOnArmingGraceTime) }, - { "scheduler_optimize_rate", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON_AUTO }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, schedulerOptimizeRate) }, { "enable_stick_arming", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_SYSTEM_CONFIG, offsetof(systemConfig_t, enableStickArming) }, // PG_VTX_CONFIG diff --git a/src/main/config/config.c b/src/main/config/config.c index 36846a66f1..708a95347a 100644 --- a/src/main/config/config.c +++ b/src/main/config/config.c @@ -109,7 +109,7 @@ PG_RESET_TEMPLATE(pilotConfig_t, pilotConfig, .displayName = { 0 }, ); -PG_REGISTER_WITH_RESET_TEMPLATE(systemConfig_t, systemConfig, PG_SYSTEM_CONFIG, 2); +PG_REGISTER_WITH_RESET_TEMPLATE(systemConfig_t, systemConfig, PG_SYSTEM_CONFIG, 3); PG_RESET_TEMPLATE(systemConfig_t, systemConfig, .pidProfileIndex = 0, @@ -122,7 +122,6 @@ PG_RESET_TEMPLATE(systemConfig_t, systemConfig, .boardIdentifier = TARGET_BOARD_IDENTIFIER, .hseMhz = SYSTEM_HSE_VALUE, // Only used for F4 and G4 targets .configurationState = CONFIGURATION_STATE_DEFAULTS_BARE, - .schedulerOptimizeRate = SCHEDULER_OPTIMIZE_RATE_AUTO, .enableStickArming = false, ); @@ -157,7 +156,6 @@ void resetConfig(void) static void activateConfig(void) { - schedulerOptimizeRate(systemConfig()->schedulerOptimizeRate == SCHEDULER_OPTIMIZE_RATE_ON || (systemConfig()->schedulerOptimizeRate == SCHEDULER_OPTIMIZE_RATE_AUTO && motorConfig()->dev.useDshotTelemetry)); loadPidProfile(); loadControlRateProfile(); @@ -513,7 +511,7 @@ static void validateAndFixConfig(void) } } - if ((!configuredMotorProtocolDshot || (motorConfig()->dev.useDshotBitbang == DSHOT_BITBANG_OFF && (motorConfig()->dev.useBurstDshot == DSHOT_DMAR_ON || nChannelTimerUsed)) || systemConfig()->schedulerOptimizeRate == SCHEDULER_OPTIMIZE_RATE_OFF) && motorConfig()->dev.useDshotTelemetry) { + if ((!configuredMotorProtocolDshot || (motorConfig()->dev.useDshotBitbang == DSHOT_BITBANG_OFF && (motorConfig()->dev.useBurstDshot == DSHOT_DMAR_ON || nChannelTimerUsed))) && motorConfig()->dev.useDshotTelemetry) { motorConfigMutable()->dev.useDshotTelemetry = false; } #endif // USE_DSHOT_TELEMETRY diff --git a/src/main/config/config.h b/src/main/config/config.h index aa218e53a8..4d7fff7ad5 100644 --- a/src/main/config/config.h +++ b/src/main/config/config.h @@ -33,12 +33,6 @@ typedef enum { CONFIGURATION_STATE_CONFIGURED, } configurationState_e; -typedef enum { - SCHEDULER_OPTIMIZE_RATE_OFF = 0, - SCHEDULER_OPTIMIZE_RATE_ON, - SCHEDULER_OPTIMIZE_RATE_AUTO, -} schedulerOptimizeRate_e; - typedef struct pilotConfig_s { char name[MAX_NAME_LENGTH + 1]; char displayName[MAX_NAME_LENGTH + 1]; @@ -57,7 +51,6 @@ typedef struct systemConfig_s { char boardIdentifier[sizeof(TARGET_BOARD_IDENTIFIER) + 1]; uint8_t hseMhz; // Only used for F4 and G4 targets uint8_t configurationState; // The state of the configuration (defaults / configured) - uint8_t schedulerOptimizeRate; uint8_t enableStickArming; // boolean that determines whether stick arming can be used } systemConfig_t; diff --git a/src/main/drivers/light_ws2811strip.c b/src/main/drivers/light_ws2811strip.c index ff4ead7071..81499e8d41 100644 --- a/src/main/drivers/light_ws2811strip.c +++ b/src/main/drivers/light_ws2811strip.c @@ -181,7 +181,7 @@ void ws2811UpdateStrip(ledStripFormatRGB_e ledFormat) { // don't wait - risk of infinite block, just get an update next time round if (!ws2811Initialised || ws2811LedDataTransferInProgress) { - ignoreTaskStateTime(); + schedulerIgnoreTaskStateTime(); return; } diff --git a/src/main/fc/dispatch.c b/src/main/fc/dispatch.c index 1e105fb797..0ea7b825a2 100644 --- a/src/main/fc/dispatch.c +++ b/src/main/fc/dispatch.c @@ -30,6 +30,8 @@ #include "fc/dispatch.h" +#include "scheduler/scheduler.h" + static dispatchEntry_t *head = NULL; static bool dispatchEnabled = false; @@ -43,10 +45,10 @@ void dispatchEnable(void) dispatchEnabled = true; } -void dispatchProcess(uint32_t currentTime) +void dispatchProcess(uint32_t currentTimeUs) { for (dispatchEntry_t **p = &head; *p; ) { - if (cmp32(currentTime, (*p)->delayedUntil) < 0) + if (cmp32(currentTimeUs, (*p)->delayedUntil) < 0) break; // unlink entry first, so handler can replan self dispatchEntry_t *current = *p; diff --git a/src/main/fc/tasks.c b/src/main/fc/tasks.c index 8e43f32771..aab5ce5bd5 100644 --- a/src/main/fc/tasks.c +++ b/src/main/fc/tasks.c @@ -113,8 +113,11 @@ #include "tasks.h" +// taskUpdateRxMain() has occasional peaks in execution time so normal moving average duration estimation doesn't work +// Decay the estimated max task duration by 1/(1 << RX_TASK_DECAY_SHIFT) on every invocation +#define RX_TASK_DECAY_SHIFT 5 // Add a margin to the task duration estimation -#define RX_TASK_MARGIN 5 +#define RX_TASK_MARGIN 1 static void taskMain(timeUs_t currentTimeUs) { @@ -179,14 +182,13 @@ bool taskUpdateRxMainInProgress() static void taskUpdateRxMain(timeUs_t currentTimeUs) { - static timeUs_t rxStateDurationUs[RX_STATE_COUNT]; + static timeUs_t rxStateDurationFracUs[RX_STATE_COUNT]; timeUs_t executeTimeUs; - timeUs_t existingDurationUs; rxState_e oldRxState = rxState; // Where we are using a state machine call schedulerIgnoreTaskExecRate() for all states bar one if (rxState != RX_STATE_UPDATE) { - ignoreTaskExecRate(); + schedulerIgnoreTaskExecRate(); } switch (rxState) { @@ -222,22 +224,20 @@ static void taskUpdateRxMain(timeUs_t currentTimeUs) break; } - if (getIgnoreTaskExecTime()) { + if (schedulerGetIgnoreTaskExecTime()) { return; } - executeTimeUs = micros() - currentTimeUs; + executeTimeUs = micros() - currentTimeUs + RX_TASK_MARGIN; - existingDurationUs = rxStateDurationUs[oldRxState] / TASK_STATS_MOVING_SUM_COUNT; - - // If the execution time is higher than expected, double the weight in the moving average - if (executeTimeUs > existingDurationUs) { - rxStateDurationUs[oldRxState] += executeTimeUs - existingDurationUs; + if (executeTimeUs > (rxStateDurationFracUs[oldRxState] >> RX_TASK_DECAY_SHIFT)) { + rxStateDurationFracUs[oldRxState] = executeTimeUs << RX_TASK_DECAY_SHIFT; + } else { + // Slowly decay the max time + rxStateDurationFracUs[oldRxState]--; } - rxStateDurationUs[oldRxState] += executeTimeUs - existingDurationUs; - - schedulerSetNextStateTime((rxStateDurationUs[rxState] / TASK_STATS_MOVING_SUM_COUNT) + RX_TASK_MARGIN); + schedulerSetNextStateTime(rxStateDurationFracUs[rxState] >> RX_TASK_DECAY_SHIFT); } diff --git a/src/main/flight/imu.c b/src/main/flight/imu.c index 38ad16a46b..60fe40d33d 100644 --- a/src/main/flight/imu.c +++ b/src/main/flight/imu.c @@ -593,7 +593,7 @@ void imuUpdateAttitude(timeUs_t currentTimeUs) acc.accADC[X] = 0; acc.accADC[Y] = 0; acc.accADC[Z] = 0; - ignoreTaskStateTime(); + schedulerIgnoreTaskStateTime(); } } #endif // USE_ACC diff --git a/src/main/flight/position.c b/src/main/flight/position.c index db78036c11..2b783dadf7 100644 --- a/src/main/flight/position.c +++ b/src/main/flight/position.c @@ -96,7 +96,7 @@ void calculateEstimatedAltitude(timeUs_t currentTimeUs) const uint32_t dTime = currentTimeUs - previousTimeUs; if (dTime < BARO_UPDATE_FREQUENCY_40HZ) { - ignoreTaskExecTime(); + schedulerIgnoreTaskExecTime(); return; } previousTimeUs = currentTimeUs; diff --git a/src/main/io/beeper.c b/src/main/io/beeper.c index 557f647534..da27704fd5 100644 --- a/src/main/io/beeper.c +++ b/src/main/io/beeper.c @@ -49,6 +49,8 @@ #include "pg/beeper.h" +#include "scheduler/scheduler.h" + #include "sensors/battery.h" #include "sensors/sensors.h" @@ -390,6 +392,7 @@ void beeperUpdate(timeUs_t currentTimeUs) } if (beeperNextToggleTime > currentTimeUs) { + schedulerIgnoreTaskExecTime(); return; } diff --git a/src/main/io/ledstrip.c b/src/main/io/ledstrip.c index 59cf89cbd2..a3753bec32 100644 --- a/src/main/io/ledstrip.c +++ b/src/main/io/ledstrip.c @@ -1066,8 +1066,8 @@ static void applyStatusProfile(timeUs_t now) { } if (!timActive) { - // Call ignoreTaskExecTime() unless data is being processed - ignoreTaskExecTime(); + // Call schedulerIgnoreTaskExecTime() unless data is being processed + schedulerIgnoreTaskExecTime(); return; // no change this update, keep old state } @@ -1248,13 +1248,11 @@ static void applySimpleProfile(timeUs_t currentTimeUs) void ledStripUpdate(timeUs_t currentTimeUs) { -#ifndef USE_LED_STRIP_STATUS_MODE UNUSED(currentTimeUs); -#endif if (!isWS2811LedStripReady()) { - // Call ignoreTaskExecTime() unless data is being processed - ignoreTaskExecTime(); + // Call schedulerIgnoreTaskExecTime() unless data is being processed + schedulerIgnoreTaskExecTime(); return; } @@ -1282,8 +1280,8 @@ void ledStripUpdate(timeUs_t currentTimeUs) break; } } else { - // Call ignoreTaskExecTime() unless data is being processed - ignoreTaskExecTime(); + // Call schedulerIgnoreTaskExecTime() unless data is being processed + schedulerIgnoreTaskExecTime(); } } diff --git a/src/main/msp/msp.c b/src/main/msp/msp.c index 744259893d..b2ec8709cc 100644 --- a/src/main/msp/msp.c +++ b/src/main/msp/msp.c @@ -2889,7 +2889,7 @@ static mspResult_e mspProcessInCommand(mspDescriptor_t srcDesc, int16_t cmdMSP, // This is going to take some time and won't be done where real-time performance is needed so // ignore how long it takes to avoid confusing the scheduler - ignoreTaskStateTime(); + schedulerIgnoreTaskStateTime(); writeEEPROM(); readEEPROM(); diff --git a/src/main/osd/osd.c b/src/main/osd/osd.c index 41ab986279..934c9055f6 100644 --- a/src/main/osd/osd.c +++ b/src/main/osd/osd.c @@ -195,6 +195,10 @@ const osd_stats_e osdStatsDisplayOrder[OSD_STAT_COUNT] = { // Allow a margin by which a group render can exceed that of the sum of the elements before declaring insane // This will most likely be violated by a USB interrupt whilst using the CLI #define OSD_ELEMENT_RENDER_GROUP_MARGIN 5 +// Safe margin when rendering elements +#define OSD_ELEMENT_RENDER_MARGIN 5 +// Safe margin in other states +#define OSD_MARGIN 2 // Format a float to the specified number of decimal places with optional rounding. // OSD symbols can optionally be placed before and after the formatted number (use SYM_NONE for no symbol). @@ -1073,7 +1077,7 @@ void osdUpdate(timeUs_t currentTimeUs) osdState_e osdCurState = osdState; if (osdState != OSD_STATE_UPDATE_CANVAS) { - ignoreTaskExecRate(); + schedulerIgnoreTaskExecRate(); } switch (osdState) { @@ -1083,7 +1087,7 @@ void osdUpdate(timeUs_t currentTimeUs) if (osdDisplayPortDeviceType == OSD_DISPLAYPORT_DEVICE_FRSKYOSD) { displayRedraw(osdDisplayPort); } else { - ignoreTaskExecTime(); + schedulerIgnoreTaskExecTime(); } return; } @@ -1309,14 +1313,14 @@ void osdUpdate(timeUs_t currentTimeUs) } if (osdState == OSD_STATE_UPDATE_ELEMENTS) { - schedulerSetNextStateTime(osdElementGroupDurationUs[osdElementGroup]); + schedulerSetNextStateTime(osdElementGroupDurationUs[osdElementGroup] + OSD_ELEMENT_RENDER_MARGIN); } else { if (osdState == OSD_STATE_IDLE) { - schedulerSetNextStateTime(osdStateDurationUs[OSD_STATE_CHECK]); + schedulerSetNextStateTime(osdStateDurationUs[OSD_STATE_CHECK] + OSD_MARGIN); } else { - schedulerSetNextStateTime(osdStateDurationUs[osdState]); + schedulerSetNextStateTime(osdStateDurationUs[osdState] + OSD_MARGIN); } - ignoreTaskExecTime(); + schedulerIgnoreTaskExecTime(); } } diff --git a/src/main/scheduler/scheduler.c b/src/main/scheduler/scheduler.c index e6ab4c37dc..a6d10784b3 100644 --- a/src/main/scheduler/scheduler.c +++ b/src/main/scheduler/scheduler.c @@ -179,6 +179,8 @@ void taskSystemLoad(timeUs_t currentTimeUs) averageSystemLoadPercent = 100 * taskTotalExecutionTime / deltaTime; taskTotalExecutionTime = 0; lastExecutedAtUs = currentTimeUs; + } else { + schedulerIgnoreTaskExecTime(); } #if defined(SIMULATOR_BUILD) @@ -208,7 +210,7 @@ void getTaskInfo(taskId_e taskId, taskInfo_t * taskInfo) taskInfo->subTaskName = getTask(taskId)->subTaskName; taskInfo->maxExecutionTimeUs = getTask(taskId)->maxExecutionTimeUs; taskInfo->totalExecutionTimeUs = getTask(taskId)->totalExecutionTimeUs; - taskInfo->averageExecutionTimeUs = getTask(taskId)->anticipatedExecutionTimeUs / TASK_STATS_MOVING_SUM_COUNT; + taskInfo->averageExecutionTimeUs = getTask(taskId)->anticipatedExecutionTime >> TASK_EXEC_TIME_SHIFT; taskInfo->averageDeltaTimeUs = getTask(taskId)->movingSumDeltaTimeUs / TASK_STATS_MOVING_SUM_COUNT; taskInfo->latestDeltaTimeUs = getTask(taskId)->taskLatestDeltaTimeUs; taskInfo->movingAverageCycleTimeUs = getTask(taskId)->movingAverageCycleTimeUs; @@ -262,25 +264,25 @@ timeDelta_t getTaskDeltaTimeUs(taskId_e taskId) } // Called by tasks executing what are known to be short states -void ignoreTaskStateTime() +void schedulerIgnoreTaskStateTime() { ignoreCurrentTaskExecRate = true; ignoreCurrentTaskExecTime = true; } // Called by tasks with state machines to only count one state as determining rate -void ignoreTaskExecRate() +void schedulerIgnoreTaskExecRate() { ignoreCurrentTaskExecRate = true; } // Called by tasks without state machines executing in what is known to be a shorter time than peak -void ignoreTaskExecTime() +void schedulerIgnoreTaskExecTime() { ignoreCurrentTaskExecTime = true; } -bool getIgnoreTaskExecTime() +bool schedulerGetIgnoreTaskExecTime() { return ignoreCurrentTaskExecTime; } @@ -288,12 +290,12 @@ bool getIgnoreTaskExecTime() void schedulerResetTaskStatistics(taskId_e taskId) { if (taskId == TASK_SELF) { - currentTask->anticipatedExecutionTimeUs = 0; + currentTask->anticipatedExecutionTime = 0; currentTask->movingSumDeltaTimeUs = 0; currentTask->totalExecutionTimeUs = 0; currentTask->maxExecutionTimeUs = 0; } else if (taskId < TASK_COUNT) { - getTask(taskId)->anticipatedExecutionTimeUs = 0; + getTask(taskId)->anticipatedExecutionTime = 0; getTask(taskId)->movingSumDeltaTimeUs = 0; getTask(taskId)->totalExecutionTimeUs = 0; getTask(taskId)->maxExecutionTimeUs = 0; @@ -343,11 +345,10 @@ void schedulerInit(void) #if defined(USE_LATE_TASK_STATISTICS) nextTimingCycles = lastTargetCycles; #endif -} -void schedulerOptimizeRate(bool optimizeRate) -{ - optimizeSchedRate = optimizeRate; + for (taskId_e taskId = 0; taskId < TASK_COUNT; taskId++) { + schedulerResetTaskStatistics(taskId); + } } inline static timeUs_t getPeriodCalculationBasis(const task_t* task) @@ -393,9 +394,14 @@ FAST_CODE timeUs_t schedulerExecuteTask(task_t *selectedTask, timeUs_t currentTi // Update estimate of expected task duration if (taskNextStateTime != -1) { - selectedTask->anticipatedExecutionTimeUs = taskNextStateTime * TASK_STATS_MOVING_SUM_COUNT; + selectedTask->anticipatedExecutionTime = taskNextStateTime << TASK_EXEC_TIME_SHIFT; } else if (!ignoreCurrentTaskExecTime) { - selectedTask->anticipatedExecutionTimeUs += taskExecutionTimeUs - selectedTask->anticipatedExecutionTimeUs / TASK_STATS_MOVING_SUM_COUNT; + if (taskExecutionTimeUs > (selectedTask->anticipatedExecutionTime >> TASK_EXEC_TIME_SHIFT)) { + selectedTask->anticipatedExecutionTime = taskExecutionTimeUs << TASK_EXEC_TIME_SHIFT; + } else if (selectedTask->anticipatedExecutionTime > 1) { + // Slowly decay the max time + selectedTask->anticipatedExecutionTime--; + } } if (!ignoreCurrentTaskExecTime) { @@ -602,7 +608,7 @@ FAST_CODE void scheduler(void) } if (selectedTask) { - timeDelta_t taskRequiredTimeUs = selectedTask->anticipatedExecutionTimeUs / TASK_STATS_MOVING_SUM_COUNT; + timeDelta_t taskRequiredTimeUs = selectedTask->anticipatedExecutionTime >> TASK_EXEC_TIME_SHIFT; #if defined(USE_LATE_TASK_STATISTICS) selectedTask->execTime = taskRequiredTimeUs; #endif @@ -636,7 +642,7 @@ FAST_CODE void scheduler(void) if (taskGuardCycles < taskGuardMaxCycles) { taskGuardCycles += taskGuardDeltaUpCycles; } - } else if (taskGuardCycles > taskGuardMinCycles) { + } else if (taskGuardCycles > taskGuardMinCycles) { taskGuardCycles -= taskGuardDeltaDownCycles; } #if defined(USE_LATE_TASK_STATISTICS) @@ -645,7 +651,7 @@ FAST_CODE void scheduler(void) } else if (selectedTask->taskAgeCycles > TASK_AGE_EXPEDITE_COUNT) { // If a task has been unable to run, then reduce it's recorded estimated run time to ensure // it's ultimate scheduling - selectedTask->anticipatedExecutionTimeUs *= TASK_AGE_EXPEDITE_SCALE; + selectedTask->anticipatedExecutionTime *= TASK_AGE_EXPEDITE_SCALE; } } } diff --git a/src/main/scheduler/scheduler.h b/src/main/scheduler/scheduler.h index 3c9805655c..e38fe4ae89 100644 --- a/src/main/scheduler/scheduler.h +++ b/src/main/scheduler/scheduler.h @@ -27,7 +27,7 @@ #define TASK_PERIOD_MS(ms) ((ms) * 1000) #define TASK_PERIOD_US(us) (us) -#define TASK_STATS_MOVING_SUM_COUNT 32 +#define TASK_STATS_MOVING_SUM_COUNT 64 #define LOAD_PERCENTAGE_ONE 100 @@ -36,13 +36,17 @@ #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_MIN_US 4 // Add an amount to the estimate of a task duration +#define TASK_GUARD_MARGIN_MAX_US 6 #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 +// Some tasks have occasional peaks in execution time so normal moving average duration estimation doesn't work +// Decay the estimated max task duration by 1/(1 << TASK_EXEC_TIME_SHIFT) on every invocation +#define TASK_EXEC_TIME_SHIFT 7 + #define TASK_AGE_EXPEDITE_COUNT 1 // Make aged tasks more schedulable #define TASK_AGE_EXPEDITE_SCALE 0.9 // By scaling their expected execution time @@ -196,7 +200,7 @@ typedef struct { // Statistics float movingAverageCycleTimeUs; - timeUs_t anticipatedExecutionTimeUs; // moving sum over 32 samples + timeUs_t anticipatedExecutionTime; // Fixed point expectation of next execution time timeUs_t movingSumDeltaTimeUs; // moving sum over 32 samples timeUs_t maxExecutionTimeUs; timeUs_t totalExecutionTimeUs; // total time consumed by task since boot @@ -213,21 +217,18 @@ 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 schedulerIgnoreTaskStateTime(); +void schedulerIgnoreTaskExecRate(); +void schedulerIgnoreTaskExecTime(); +bool schedulerGetIgnoreTaskExecTime(); 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); diff --git a/src/main/sensors/barometer.c b/src/main/sensors/barometer.c index df51e8d6a9..e02836347a 100644 --- a/src/main/sensors/barometer.c +++ b/src/main/sensors/barometer.c @@ -388,14 +388,14 @@ uint32_t baroUpdate(timeUs_t currentTimeUs) DEBUG_SET(DEBUG_BARO, 0, state); - // Where we are using a state machine call ignoreTaskExecRate() for all states bar one + // Where we are using a state machine call schedulerIgnoreTaskExecRate() for all states bar one if (state != BARO_STATE_TEMPERATURE_START) { - ignoreTaskExecRate(); + schedulerIgnoreTaskExecRate(); } if (busBusy(&baro.dev.dev, NULL)) { // If the bus is busy, simply return to have another go later - ignoreTaskStateTime(); + schedulerIgnoreTaskStateTime(); return sleepTime; } @@ -429,7 +429,7 @@ uint32_t baroUpdate(timeUs_t currentTimeUs) if (baro.dev.read_up(&baro.dev)) { state = BARO_STATE_PRESSURE_SAMPLE; } else { - ignoreTaskStateTime(); + schedulerIgnoreTaskStateTime(); } break; diff --git a/src/main/sensors/battery.c b/src/main/sensors/battery.c index fdae959a9f..4c82131dd3 100644 --- a/src/main/sensors/battery.c +++ b/src/main/sensors/battery.c @@ -45,6 +45,8 @@ #include "pg/pg.h" #include "pg/pg_ids.h" +#include "scheduler/scheduler.h" + #include "sensors/battery.h" /** @@ -409,12 +411,10 @@ void batteryInit(void) default: break; } - } void batteryUpdateCurrentMeter(timeUs_t currentTimeUs) { - UNUSED(currentTimeUs); if (batteryCellCount == 0) { currentMeterReset(¤tMeter); return; diff --git a/src/test/unit/arming_prevention_unittest.cc b/src/test/unit/arming_prevention_unittest.cc index b6d3438089..df2d4bcd32 100644 --- a/src/test/unit/arming_prevention_unittest.cc +++ b/src/test/unit/arming_prevention_unittest.cc @@ -1108,4 +1108,5 @@ extern "C" { uint16_t getAverageSystemLoadPercent(void) { return 0; } bool isMotorProtocolEnabled(void) { return true; } void pinioBoxTaskControl(void) {} + void schedulerSetNextStateTime(timeDelta_t) {} } diff --git a/src/test/unit/flight_imu_unittest.cc b/src/test/unit/flight_imu_unittest.cc index 50ef8b8979..5c04c02e82 100644 --- a/src/test/unit/flight_imu_unittest.cc +++ b/src/test/unit/flight_imu_unittest.cc @@ -250,6 +250,8 @@ void mixerSetThrottleAngleCorrection(int) {}; bool gpsRescueIsRunning(void) { return false; } bool isFixedWing(void) { return false; } void pinioBoxTaskControl(void) {} -void ignoreTaskExecTime(void) {} -void ignoreTaskStateTime(void) {} +void schedulerIgnoreTaskExecTime(void) {} +void schedulerIgnoreTaskStateTime(void) {} +void schedulerSetNextStateTime(timeDelta_t) {} +bool schedulerGetIgnoreTaskExecTime() { return false; } } diff --git a/src/test/unit/ledstrip_unittest.cc b/src/test/unit/ledstrip_unittest.cc index 65f13f5816..d4521cafc0 100644 --- a/src/test/unit/ledstrip_unittest.cc +++ b/src/test/unit/ledstrip_unittest.cc @@ -397,5 +397,7 @@ void ws2811LedStripEnable(void) { } void setUsedLedCount(unsigned) { } void pinioBoxTaskControl(void) {} -void ignoreTaskExecTime(void) {} +void schedulerIgnoreTaskExecTime(void) {} +bool schedulerGetIgnoreTaskExecTime() { return false; } +void schedulerSetNextStateTime(timeDelta_t) {} } diff --git a/src/test/unit/link_quality_unittest.cc b/src/test/unit/link_quality_unittest.cc index cd21cb0e03..38399218cd 100644 --- a/src/test/unit/link_quality_unittest.cc +++ b/src/test/unit/link_quality_unittest.cc @@ -510,9 +510,9 @@ extern "C" { void failsafeOnValidDataFailed(void) { } void pinioBoxTaskControl(void) { } bool taskUpdateRxMainInProgress() { return true; } - void ignoreTaskStateTime(void) { } - void ignoreTaskExecRate(void) { } - void ignoreTaskExecTime(void) { } + void schedulerIgnoreTaskStateTime(void) { } + void schedulerIgnoreTaskExecRate(void) { } + void schedulerIgnoreTaskExecTime(void) { } void schedulerSetNextStateTime(timeDelta_t) {} void rxPwmInit(rxRuntimeState_t *rxRuntimeState, rcReadRawDataFnPtr *callback) diff --git a/src/test/unit/osd_unittest.cc b/src/test/unit/osd_unittest.cc index ecf472b4ab..3272f83027 100644 --- a/src/test/unit/osd_unittest.cc +++ b/src/test/unit/osd_unittest.cc @@ -1376,8 +1376,8 @@ extern "C" { bool isUpright(void) { return true; } float getMotorOutputLow(void) { return 1000.0; } float getMotorOutputHigh(void) { return 2047.0; } - void ignoreTaskStateTime(void) { } - void ignoreTaskExecRate(void) { } - void ignoreTaskExecTime(void) { } + void schedulerIgnoreTaskStateTime(void) { } + void schedulerIgnoreTaskExecRate(void) { } + void schedulerIgnoreTaskExecTime(void) { } void schedulerSetNextStateTime(timeDelta_t) {} } diff --git a/src/test/unit/vtx_unittest.cc b/src/test/unit/vtx_unittest.cc index e7897e010b..d7d1c2f277 100644 --- a/src/test/unit/vtx_unittest.cc +++ b/src/test/unit/vtx_unittest.cc @@ -197,5 +197,5 @@ extern "C" { void sbufWriteU8(sbuf_t *, uint8_t) {} void sbufWriteU16(sbuf_t *, uint16_t) {} void sbufWriteU32(sbuf_t *, uint32_t) {} - + void schedulerSetNextStateTime(timeDelta_t) {} } diff --git a/src/test/unit/ws2811_unittest.cc b/src/test/unit/ws2811_unittest.cc index 796940001a..4340d6ef7d 100644 --- a/src/test/unit/ws2811_unittest.cc +++ b/src/test/unit/ws2811_unittest.cc @@ -32,8 +32,8 @@ extern "C" { extern "C" { void updateLEDDMABuffer(ledStripFormatRGB_e ledFormat, rgbColor24bpp_t *color, unsigned ledIndex); - void ignoreTaskExecTime(void) {} - void ignoreTaskStateTime(void) {} + void schedulerIgnoreTaskExecTime(void) {} + void schedulerIgnoreTaskStateTime(void) {} } TEST(WS2812, updateDMABuffer) { From d94a78cb3ec97649a44c8dd9ed948e312c0ab88f Mon Sep 17 00:00:00 2001 From: Steve Evans Date: Sat, 18 Dec 2021 13:36:55 +0000 Subject: [PATCH 2/2] Reduce timing margins --- src/main/scheduler/scheduler.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/scheduler/scheduler.h b/src/main/scheduler/scheduler.h index e38fe4ae89..1f54ab5b28 100644 --- a/src/main/scheduler/scheduler.h +++ b/src/main/scheduler/scheduler.h @@ -31,12 +31,12 @@ #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_MIN_US 1 // 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 4 // Add an amount to the estimate of a task duration +#define TASK_GUARD_MARGIN_MIN_US 1 // Add an amount to the estimate of a task duration #define TASK_GUARD_MARGIN_MAX_US 6 #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