diff --git a/src/main/cli/settings.c b/src/main/cli/settings.c index 9f654aaa93c..e6e771a158b 100644 --- a/src/main/cli/settings.c +++ b/src/main/cli/settings.c @@ -1717,8 +1717,10 @@ const clivalue_t valueTable[] = { { "expresslrs_model_id", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, UINT8_MAX }, PG_RX_EXPRESSLRS_SPI_CONFIG, offsetof(rxExpressLrsSpiConfig_t, modelId) }, #endif - { "scheduler_relax_rx", VAR_UINT16 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_SCHEDULER_CONFIG, PG_ARRAY_ELEMENT_OFFSET(schedulerConfig_t, 0, rxRelaxDeterminism) }, - { "scheduler_relax_osd", VAR_UINT16 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_SCHEDULER_CONFIG, PG_ARRAY_ELEMENT_OFFSET(schedulerConfig_t, 0, osdRelaxDeterminism) }, + { "scheduler_relax_rx", VAR_UINT16 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_SCHEDULER_CONFIG, offsetof(schedulerConfig_t, rxRelaxDeterminism) }, + { "scheduler_relax_osd", VAR_UINT16 | HARDWARE_VALUE, .config.minmaxUnsigned = { 0, 500 }, PG_SCHEDULER_CONFIG, offsetof(schedulerConfig_t, osdRelaxDeterminism) }, + + { "cpu_late_percent_limit", VAR_UINT8 | MASTER_VALUE, .config.minmaxUnsigned = { 0, 100 }, PG_SCHEDULER_CONFIG, offsetof(schedulerConfig_t, cpuLatePercentageLimit) }, { "serialmsp_halfduplex", VAR_UINT8 | MASTER_VALUE | MODE_LOOKUP, .config.lookup = { TABLE_OFF_ON }, PG_MSP_CONFIG, offsetof(mspConfig_t, halfDuplex) }, diff --git a/src/main/fc/core.c b/src/main/fc/core.c index ef1898bf176..9d757eb4725 100644 --- a/src/main/fc/core.c +++ b/src/main/fc/core.c @@ -323,11 +323,13 @@ void updateArmingStatus(void) unsetArmingDisabled(ARMING_DISABLED_ANGLE); } - if (getAverageSystemLoadPercent() > LOAD_PERCENTAGE_ONE) { +#if defined(USE_LATE_TASK_STATISTICS) + if ((getCPUPercentageLate() > schedulerConfig()->cpuLatePercentageLimit)) { setArmingDisabled(ARMING_DISABLED_LOAD); } else { unsetArmingDisabled(ARMING_DISABLED_LOAD); } +#endif // USE_LATE_TASK_STATISTICS if (isCalibrating()) { setArmingDisabled(ARMING_DISABLED_CALIBRATING); diff --git a/src/main/osd/osd.h b/src/main/osd/osd.h index d8ee847247c..ded88fb7d4f 100644 --- a/src/main/osd/osd.h +++ b/src/main/osd/osd.h @@ -281,6 +281,7 @@ typedef enum { OSD_WARNING_RSSI_DBM, OSD_WARNING_OVER_CAP, OSD_WARNING_RSNR, + OSD_WARNING_LOAD, OSD_WARNING_COUNT // MUST BE LAST } osdWarningsFlags_e; diff --git a/src/main/osd/osd_warnings.c b/src/main/osd/osd_warnings.c index d7748b8a9e6..4b5e57ccb28 100644 --- a/src/main/osd/osd_warnings.c +++ b/src/main/osd/osd_warnings.c @@ -213,6 +213,13 @@ void renderOsdWarning(char *warningText, bool *blinking, uint8_t *displayAttr) return; } + if (osdWarnGetState(OSD_WARNING_LOAD) && (getArmingDisableFlags() & ARMING_DISABLED_LOAD)) { + tfp_sprintf(warningText, "CPU OVERLOAD"); + *displayAttr = DISPLAYPORT_SEVERITY_CRITICAL; + *blinking = true; + return; + } + #ifdef USE_GPS_RESCUE if (osdWarnGetState(OSD_WARNING_GPS_RESCUE_UNAVAILABLE) && ARMING_FLAG(ARMED) && diff --git a/src/main/pg/scheduler.c b/src/main/pg/scheduler.c index 701d673f209..bb1ac8abd5e 100644 --- a/src/main/pg/scheduler.c +++ b/src/main/pg/scheduler.c @@ -28,4 +28,5 @@ PG_REGISTER_WITH_RESET_TEMPLATE(schedulerConfig_t, schedulerConfig, PG_SCHEDULER PG_RESET_TEMPLATE(schedulerConfig_t, schedulerConfig, .rxRelaxDeterminism = SCHEDULER_RELAX_RX, .osdRelaxDeterminism = SCHEDULER_RELAX_OSD, + .cpuLatePercentageLimit = SCHEDULER_LATE_LIMIT ); diff --git a/src/main/pg/scheduler.h b/src/main/pg/scheduler.h index 6bf098f3a2d..ed5bc7dd020 100644 --- a/src/main/pg/scheduler.h +++ b/src/main/pg/scheduler.h @@ -31,9 +31,13 @@ #define SCHEDULER_RELAX_OSD 25 #endif +// Tenths of a % of tasks late +#define SCHEDULER_LATE_LIMIT 50 + typedef struct schedulerConfig_s { uint16_t rxRelaxDeterminism; uint16_t osdRelaxDeterminism; + uint16_t cpuLatePercentageLimit; } schedulerConfig_t; PG_DECLARE(schedulerConfig_t, schedulerConfig); diff --git a/src/main/scheduler/scheduler.c b/src/main/scheduler/scheduler.c index a072d2205be..74e575e7c14 100644 --- a/src/main/scheduler/scheduler.c +++ b/src/main/scheduler/scheduler.c @@ -107,6 +107,7 @@ static uint8_t skippedOSDAttempts = 0; static int16_t lateTaskCount = 0; static uint32_t lateTaskTotal = 0; static int16_t taskCount = 0; +static uint32_t lateTaskPercentage = 0; static uint32_t nextTimingCycles; #endif @@ -199,6 +200,12 @@ void taskSystemLoad(timeUs_t currentTimeUs) #endif } +uint32_t getCPUPercentageLate(void) +{ + return lateTaskPercentage; + +} + timeUs_t checkFuncMaxExecutionTimeUs; timeUs_t checkFuncTotalExecutionTimeUs; timeUs_t checkFuncMovingSumExecutionTimeUs; @@ -535,6 +542,7 @@ FAST_CODE void scheduler(void) // Total tasks run in last second DEBUG_SET(DEBUG_TIMING_ACCURACY, 3, taskCount); + lateTaskPercentage = 1000 * (uint32_t)lateTaskCount / taskCount; lateTaskCount = 0; lateTaskTotal = 0; taskCount = 0; diff --git a/src/main/scheduler/scheduler.h b/src/main/scheduler/scheduler.h index d18511378bd..983baa68dbe 100644 --- a/src/main/scheduler/scheduler.h +++ b/src/main/scheduler/scheduler.h @@ -243,6 +243,7 @@ void schedulerInit(void); void scheduler(void); timeUs_t schedulerExecuteTask(task_t *selectedTask, timeUs_t currentTimeUs); void taskSystemLoad(timeUs_t currentTimeUs); +uint32_t getCPUPercentageLate(void); void schedulerEnableGyro(void); uint16_t getAverageSystemLoadPercent(void); float schedulerGetCycleTimeMultiplier(void); diff --git a/src/test/unit/arming_prevention_unittest.cc b/src/test/unit/arming_prevention_unittest.cc index cc345147c46..162e95aedc0 100644 --- a/src/test/unit/arming_prevention_unittest.cc +++ b/src/test/unit/arming_prevention_unittest.cc @@ -1161,4 +1161,5 @@ extern "C" { return 0.0f; } void getRcDeflectionAbs(void) {} + uint32_t getCPUPercentageLate(void) { return 0; }; }