mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-23 16:25:31 +03:00
Cleaned up the scheduler.
This commit is contained in:
parent
b729c3cc99
commit
db4bd1f186
20 changed files with 326 additions and 392 deletions
|
@ -1051,7 +1051,7 @@ extern "C" {
|
|||
bool calculateRxChannelsAndUpdateFailsafe(timeUs_t) { return true; }
|
||||
bool isMixerUsingServos(void) { return false; }
|
||||
void gyroUpdate(void) {}
|
||||
timeDelta_t getTaskDeltaTime(cfTaskId_e) { return 0; }
|
||||
timeDelta_t getTaskDeltaTimeUs(taskId_e) { return 0; }
|
||||
void updateRSSI(timeUs_t) {}
|
||||
bool failsafeIsMonitoring(void) { return false; }
|
||||
void failsafeStartMonitoring(void) {}
|
||||
|
@ -1082,7 +1082,7 @@ extern "C" {
|
|||
void dashboardEnablePageCycling(void) {}
|
||||
void dashboardDisablePageCycling(void) {}
|
||||
bool imuQuaternionHeadfreeOffsetSet(void) { return true; }
|
||||
void rescheduleTask(cfTaskId_e, uint32_t) {}
|
||||
void rescheduleTask(taskId_e, timeDelta_t) {}
|
||||
bool usbCableIsInserted(void) { return false; }
|
||||
bool usbVcpIsConnected(void) { return false; }
|
||||
void pidSetAntiGravityState(bool) {}
|
||||
|
@ -1103,4 +1103,5 @@ extern "C" {
|
|||
void gyroFiltering(timeUs_t) {};
|
||||
timeDelta_t rxGetFrameDelta(timeDelta_t *) { return 0; }
|
||||
void updateRcRefreshRate(timeUs_t) {};
|
||||
uint16_t getAverageSystemLoadPercent(void) { return 0; }
|
||||
}
|
||||
|
|
|
@ -299,7 +299,7 @@ uint8_t __config_start = 0x00;
|
|||
uint8_t __config_end = 0x10;
|
||||
uint16_t averageSystemLoadPercent = 0;
|
||||
|
||||
timeDelta_t getTaskDeltaTime(cfTaskId_e){ return 0; }
|
||||
timeDelta_t getTaskDeltaTimeUs(taskId_e){ return 0; }
|
||||
uint16_t currentRxRefreshRate = 9000;
|
||||
armingDisableFlags_e getArmingDisableFlags(void) { return ARMING_DISABLED_NO_GYRO; }
|
||||
|
||||
|
@ -307,9 +307,9 @@ const char *armingDisableFlagNames[]= {
|
|||
"DUMMYDISABLEFLAGNAME"
|
||||
};
|
||||
|
||||
void getTaskInfo(cfTaskId_e, cfTaskInfo_t *) {}
|
||||
void getTaskInfo(taskId_e, taskInfo_t *) {}
|
||||
void getCheckFuncInfo(cfCheckFuncInfo_t *) {}
|
||||
void schedulerResetTaskMaxExecutionTime(cfTaskId_e) {}
|
||||
void schedulerResetTaskMaxExecutionTime(taskId_e) {}
|
||||
void schedulerResetCheckFunctionMaxExecutionTime(void) {}
|
||||
|
||||
const char * const targetName = "UNITTEST";
|
||||
|
@ -360,4 +360,5 @@ void delay(uint32_t) {}
|
|||
displayPort_t *osdGetDisplayPort(osdDisplayPortDevice_e *) { return NULL; }
|
||||
mcuTypeId_e getMcuTypeId(void) { return MCU_TYPE_UNKNOWN; }
|
||||
uint16_t getCurrentRxRefreshRate(void) { return 0; }
|
||||
uint16_t getAverageSystemLoadPercent(void) { return 0; }
|
||||
}
|
||||
|
|
|
@ -646,7 +646,7 @@ rxRuntimeState_t rxRuntimeState;
|
|||
PG_REGISTER(blackboxConfig_t, blackboxConfig, PG_BLACKBOX_CONFIG, 0);
|
||||
PG_REGISTER(systemConfig_t, systemConfig, PG_SYSTEM_CONFIG, 2);
|
||||
void resetArmingDisabled(void) {}
|
||||
timeDelta_t getTaskDeltaTime(cfTaskId_e) { return 20000; }
|
||||
timeDelta_t getTaskDeltaTimeUs(taskId_e) { return 20000; }
|
||||
armingDisableFlags_e getArmingDisableFlags(void) {
|
||||
return (armingDisableFlags_e) 0;
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ const int TEST_DISPATCH_TIME = 1;
|
|||
#define TASK_PERIOD_HZ(hz) (1000000 / (hz))
|
||||
|
||||
extern "C" {
|
||||
cfTask_t * unittest_scheduler_selectedTask;
|
||||
task_t * unittest_scheduler_selectedTask;
|
||||
uint8_t unittest_scheduler_selectedTaskDynPrio;
|
||||
uint16_t unittest_scheduler_waitingTasks;
|
||||
timeDelta_t unittest_scheduler_taskRequiredTimeUs;
|
||||
|
@ -79,87 +79,92 @@ extern "C" {
|
|||
}
|
||||
|
||||
extern int taskQueueSize;
|
||||
extern cfTask_t* taskQueueArray[];
|
||||
extern task_t* taskQueueArray[];
|
||||
|
||||
extern void queueClear(void);
|
||||
extern bool queueContains(cfTask_t *task);
|
||||
extern bool queueAdd(cfTask_t *task);
|
||||
extern bool queueRemove(cfTask_t *task);
|
||||
extern cfTask_t *queueFirst(void);
|
||||
extern cfTask_t *queueNext(void);
|
||||
extern bool queueContains(task_t *task);
|
||||
extern bool queueAdd(task_t *task);
|
||||
extern bool queueRemove(task_t *task);
|
||||
extern task_t *queueFirst(void);
|
||||
extern task_t *queueNext(void);
|
||||
|
||||
cfTask_t cfTasks[TASK_COUNT] = {
|
||||
task_t tasks[TASK_COUNT] = {
|
||||
[TASK_SYSTEM] = {
|
||||
.taskName = "SYSTEM",
|
||||
.taskFunc = taskSystemLoad,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(10),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(10),
|
||||
.staticPriority = TASK_PRIORITY_MEDIUM_HIGH,
|
||||
},
|
||||
[TASK_GYRO] = {
|
||||
.taskName = "GYRO",
|
||||
.taskFunc = taskGyroSample,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ),
|
||||
.staticPriority = TASK_PRIORITY_REALTIME,
|
||||
},
|
||||
[TASK_FILTER] = {
|
||||
.taskName = "FILTER",
|
||||
.taskFunc = taskFiltering,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(4000),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(4000),
|
||||
.staticPriority = TASK_PRIORITY_REALTIME,
|
||||
},
|
||||
[TASK_PID] = {
|
||||
.taskName = "PID",
|
||||
.taskFunc = taskMainPidLoop,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(4000),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(4000),
|
||||
.staticPriority = TASK_PRIORITY_REALTIME,
|
||||
},
|
||||
[TASK_ACCEL] = {
|
||||
.taskName = "ACCEL",
|
||||
.taskFunc = taskUpdateAccelerometer,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(1000),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(1000),
|
||||
.staticPriority = TASK_PRIORITY_MEDIUM,
|
||||
},
|
||||
[TASK_ATTITUDE] = {
|
||||
.taskName = "ATTITUDE",
|
||||
.taskFunc = imuUpdateAttitude,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(100),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(100),
|
||||
.staticPriority = TASK_PRIORITY_MEDIUM,
|
||||
},
|
||||
[TASK_RX] = {
|
||||
.taskName = "RX",
|
||||
.checkFunc = rxUpdateCheck,
|
||||
.taskFunc = taskUpdateRxMain,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(50),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(50),
|
||||
.staticPriority = TASK_PRIORITY_HIGH,
|
||||
},
|
||||
[TASK_SERIAL] = {
|
||||
.taskName = "SERIAL",
|
||||
.taskFunc = taskHandleSerial,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(100),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(100),
|
||||
.staticPriority = TASK_PRIORITY_LOW,
|
||||
},
|
||||
[TASK_DISPATCH] = {
|
||||
.taskName = "DISPATCH",
|
||||
.taskFunc = dispatchProcess,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(1000),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(1000),
|
||||
.staticPriority = TASK_PRIORITY_HIGH,
|
||||
},
|
||||
[TASK_BATTERY_VOLTAGE] = {
|
||||
.taskName = "BATTERY_VOLTAGE",
|
||||
.taskFunc = taskUpdateBatteryVoltage,
|
||||
.desiredPeriod = TASK_PERIOD_HZ(50),
|
||||
.desiredPeriodUs = TASK_PERIOD_HZ(50),
|
||||
.staticPriority = TASK_PRIORITY_MEDIUM,
|
||||
}
|
||||
};
|
||||
|
||||
task_t *getTask(unsigned taskId)
|
||||
{
|
||||
return &tasks[taskId];
|
||||
}
|
||||
}
|
||||
|
||||
TEST(SchedulerUnittest, TestPriorites)
|
||||
{
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM_HIGH, cfTasks[TASK_SYSTEM].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_REALTIME, cfTasks[TASK_GYRO].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, cfTasks[TASK_ACCEL].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_LOW, cfTasks[TASK_SERIAL].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, cfTasks[TASK_BATTERY_VOLTAGE].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM_HIGH, tasks[TASK_SYSTEM].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_REALTIME, tasks[TASK_GYRO].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, tasks[TASK_ACCEL].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_LOW, tasks[TASK_SERIAL].staticPriority);
|
||||
EXPECT_EQ(TASK_PRIORITY_MEDIUM, tasks[TASK_BATTERY_VOLTAGE].staticPriority);
|
||||
}
|
||||
|
||||
TEST(SchedulerUnittest, TestQueueInit)
|
||||
|
@ -173,47 +178,47 @@ TEST(SchedulerUnittest, TestQueueInit)
|
|||
}
|
||||
}
|
||||
|
||||
cfTask_t *deadBeefPtr = reinterpret_cast<cfTask_t*>(0xDEADBEEF);
|
||||
task_t *deadBeefPtr = reinterpret_cast<task_t*>(0xDEADBEEF);
|
||||
|
||||
TEST(SchedulerUnittest, TestQueue)
|
||||
{
|
||||
queueClear();
|
||||
taskQueueArray[TASK_COUNT + 1] = deadBeefPtr;
|
||||
|
||||
queueAdd(&cfTasks[TASK_SYSTEM]); // TASK_PRIORITY_MEDIUM_HIGH
|
||||
queueAdd(&tasks[TASK_SYSTEM]); // TASK_PRIORITY_MEDIUM_HIGH
|
||||
EXPECT_EQ(1, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
|
||||
queueAdd(&cfTasks[TASK_SERIAL]); // TASK_PRIORITY_LOW
|
||||
queueAdd(&tasks[TASK_SERIAL]); // TASK_PRIORITY_LOW
|
||||
EXPECT_EQ(2, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(NULL, queueNext());
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
|
||||
queueAdd(&cfTasks[TASK_BATTERY_VOLTAGE]); // TASK_PRIORITY_MEDIUM
|
||||
queueAdd(&tasks[TASK_BATTERY_VOLTAGE]); // TASK_PRIORITY_MEDIUM
|
||||
EXPECT_EQ(3, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&cfTasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(NULL, queueNext());
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
|
||||
queueAdd(&cfTasks[TASK_RX]); // TASK_PRIORITY_HIGH
|
||||
queueAdd(&tasks[TASK_RX]); // TASK_PRIORITY_HIGH
|
||||
EXPECT_EQ(4, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_RX], queueFirst());
|
||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueNext());
|
||||
EXPECT_EQ(&cfTasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_RX], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_SYSTEM], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(NULL, queueNext());
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
|
||||
queueRemove(&cfTasks[TASK_SYSTEM]); // TASK_PRIORITY_HIGH
|
||||
queueRemove(&tasks[TASK_SYSTEM]); // TASK_PRIORITY_HIGH
|
||||
EXPECT_EQ(3, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_RX], queueFirst());
|
||||
EXPECT_EQ(&cfTasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&cfTasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_RX], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_BATTERY_VOLTAGE], queueNext());
|
||||
EXPECT_EQ(&tasks[TASK_SERIAL], queueNext());
|
||||
EXPECT_EQ(NULL, queueNext());
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
}
|
||||
|
@ -225,7 +230,7 @@ TEST(SchedulerUnittest, TestQueueAddAndRemove)
|
|||
|
||||
// fill up the queue
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
const bool added = queueAdd(&cfTasks[taskId]);
|
||||
const bool added = queueAdd(&tasks[taskId]);
|
||||
EXPECT_TRUE(added);
|
||||
EXPECT_EQ(taskId + 1, taskQueueSize);
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]);
|
||||
|
@ -233,13 +238,13 @@ TEST(SchedulerUnittest, TestQueueAddAndRemove)
|
|||
|
||||
// double check end of queue
|
||||
EXPECT_EQ(TASK_COUNT, taskQueueSize);
|
||||
EXPECT_NE(static_cast<cfTask_t*>(0), taskQueueArray[TASK_COUNT - 1]); // last item was indeed added to queue
|
||||
EXPECT_NE(static_cast<task_t*>(0), taskQueueArray[TASK_COUNT - 1]); // last item was indeed added to queue
|
||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT]); // null pointer at end of queue is preserved
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT + 1]); // there hasn't been an out by one error
|
||||
|
||||
// and empty it again
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
const bool removed = queueRemove(&cfTasks[taskId]);
|
||||
const bool removed = queueRemove(&tasks[taskId]);
|
||||
EXPECT_TRUE(removed);
|
||||
EXPECT_EQ(TASK_COUNT - taskId - 1, taskQueueSize);
|
||||
EXPECT_EQ(NULL, taskQueueArray[TASK_COUNT - taskId]);
|
||||
|
@ -262,16 +267,16 @@ TEST(SchedulerUnittest, TestQueueArray)
|
|||
EXPECT_EQ(enqueuedTasks, taskQueueSize);
|
||||
|
||||
for (int taskId = 0; taskId < TASK_COUNT_UNITTEST - 1; ++taskId) {
|
||||
if (cfTasks[taskId].taskFunc) {
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), true);
|
||||
if (tasks[taskId].taskFunc) {
|
||||
setTaskEnabled(static_cast<taskId_e>(taskId), true);
|
||||
enqueuedTasks++;
|
||||
EXPECT_EQ(enqueuedTasks, taskQueueSize);
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT_UNITTEST + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_NE(static_cast<cfTask_t*>(0), taskQueueArray[enqueuedTasks - 1]);
|
||||
const cfTask_t *lastTaskPrev = taskQueueArray[enqueuedTasks - 1];
|
||||
EXPECT_NE(static_cast<task_t*>(0), taskQueueArray[enqueuedTasks - 1]);
|
||||
const task_t *lastTaskPrev = taskQueueArray[enqueuedTasks - 1];
|
||||
EXPECT_EQ(NULL, taskQueueArray[enqueuedTasks]);
|
||||
EXPECT_EQ(NULL, taskQueueArray[enqueuedTasks + 1]);
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT_UNITTEST + 1]);
|
||||
|
@ -292,10 +297,10 @@ TEST(SchedulerUnittest, TestQueueArray)
|
|||
EXPECT_EQ(NULL, taskQueueArray[enqueuedTasks + 1]);
|
||||
EXPECT_EQ(deadBeefPtr, taskQueueArray[TASK_COUNT_UNITTEST + 1]);
|
||||
|
||||
cfTaskInfo_t taskInfo;
|
||||
getTaskInfo(static_cast<cfTaskId_e>(enqueuedTasks + 1), &taskInfo);
|
||||
taskInfo_t taskInfo;
|
||||
getTaskInfo(static_cast<taskId_e>(enqueuedTasks + 1), &taskInfo);
|
||||
EXPECT_FALSE(taskInfo.isEnabled);
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(enqueuedTasks), true);
|
||||
setTaskEnabled(static_cast<taskId_e>(enqueuedTasks), true);
|
||||
EXPECT_EQ(enqueuedTasks, taskQueueSize);
|
||||
EXPECT_EQ(lastTaskPrev, taskQueueArray[enqueuedTasks - 1]);
|
||||
EXPECT_EQ(NULL, taskQueueArray[enqueuedTasks + 1]); // check no buffer overrun
|
||||
|
@ -327,7 +332,7 @@ TEST(SchedulerUnittest, TestSchedulerInit)
|
|||
{
|
||||
schedulerInit();
|
||||
EXPECT_EQ(1, taskQueueSize);
|
||||
EXPECT_EQ(&cfTasks[TASK_SYSTEM], queueFirst());
|
||||
EXPECT_EQ(&tasks[TASK_SYSTEM], queueFirst());
|
||||
}
|
||||
|
||||
TEST(SchedulerUnittest, TestScheduleEmptyQueue)
|
||||
|
@ -344,27 +349,27 @@ TEST(SchedulerUnittest, TestSingleTask)
|
|||
schedulerInit();
|
||||
// disable all tasks except TASK_ACCEL
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
||||
setTaskEnabled(static_cast<taskId_e>(taskId), false);
|
||||
}
|
||||
setTaskEnabled(TASK_ACCEL, true);
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = 1000;
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = 1000;
|
||||
simulatedTime = 2050;
|
||||
// run the scheduler and check the task has executed
|
||||
scheduler();
|
||||
EXPECT_NE(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(1050, cfTasks[TASK_ACCEL].taskLatestDeltaTime);
|
||||
EXPECT_EQ(2050, cfTasks[TASK_ACCEL].lastExecutedAt);
|
||||
EXPECT_EQ(TEST_UPDATE_ACCEL_TIME, cfTasks[TASK_ACCEL].totalExecutionTime);
|
||||
EXPECT_NE(unittest_scheduler_selectedTask, static_cast<task_t*>(0));
|
||||
EXPECT_EQ(unittest_scheduler_selectedTask, &tasks[TASK_ACCEL]);
|
||||
EXPECT_EQ(1050, tasks[TASK_ACCEL].taskLatestDeltaTimeUs);
|
||||
EXPECT_EQ(2050, tasks[TASK_ACCEL].lastExecutedAtUs);
|
||||
EXPECT_EQ(TEST_UPDATE_ACCEL_TIME, tasks[TASK_ACCEL].totalExecutionTimeUs);
|
||||
// task has run, so its dynamic priority should have been set to zero
|
||||
EXPECT_EQ(0, cfTasks[TASK_GYRO].dynamicPriority);
|
||||
EXPECT_EQ(0, tasks[TASK_GYRO].dynamicPriority);
|
||||
}
|
||||
|
||||
TEST(SchedulerUnittest, TestTwoTasks)
|
||||
{
|
||||
// disable all tasks except TASK_ACCEL and TASK_ATTITUDE
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
||||
setTaskEnabled(static_cast<taskId_e>(taskId), false);
|
||||
}
|
||||
setTaskEnabled(TASK_ACCEL, true);
|
||||
setTaskEnabled(TASK_ATTITUDE, true);
|
||||
|
@ -372,49 +377,49 @@ TEST(SchedulerUnittest, TestTwoTasks)
|
|||
// set it up so that TASK_ACCEL ran just before TASK_ATTITUDE
|
||||
static const uint32_t startTime = 4000;
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = simulatedTime;
|
||||
cfTasks[TASK_ATTITUDE].lastExecutedAt = cfTasks[TASK_ACCEL].lastExecutedAt - TEST_UPDATE_ATTITUDE_TIME;
|
||||
EXPECT_EQ(0, cfTasks[TASK_ATTITUDE].taskAgeCycles);
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime;
|
||||
tasks[TASK_ATTITUDE].lastExecutedAtUs = tasks[TASK_ACCEL].lastExecutedAtUs - TEST_UPDATE_ATTITUDE_TIME;
|
||||
EXPECT_EQ(0, tasks[TASK_ATTITUDE].taskAgeCycles);
|
||||
// run the scheduler
|
||||
scheduler();
|
||||
// no tasks should have run, since neither task's desired time has elapsed
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
|
||||
// NOTE:
|
||||
// TASK_ACCEL desiredPeriod is 1000 microseconds
|
||||
// TASK_ATTITUDE desiredPeriod is 10000 microseconds
|
||||
// TASK_ACCEL desiredPeriodUs is 1000 microseconds
|
||||
// TASK_ATTITUDE desiredPeriodUs is 10000 microseconds
|
||||
// 500 microseconds later
|
||||
simulatedTime += 500;
|
||||
// no tasks should run, since neither task's desired time has elapsed
|
||||
scheduler();
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(0, unittest_scheduler_waitingTasks);
|
||||
|
||||
// 500 microseconds later, TASK_ACCEL desiredPeriod has elapsed
|
||||
// 500 microseconds later, TASK_ACCEL desiredPeriodUs has elapsed
|
||||
simulatedTime += 500;
|
||||
// TASK_ACCEL should now run
|
||||
scheduler();
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(1, unittest_scheduler_waitingTasks);
|
||||
EXPECT_EQ(5000 + TEST_UPDATE_ACCEL_TIME, simulatedTime);
|
||||
|
||||
simulatedTime += 1000 - TEST_UPDATE_ACCEL_TIME;
|
||||
scheduler();
|
||||
// TASK_ACCEL should run again
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
|
||||
scheduler();
|
||||
// No task should have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(0, unittest_scheduler_waitingTasks);
|
||||
|
||||
simulatedTime = startTime + 10500; // TASK_ACCEL and TASK_ATTITUDE desiredPeriods have elapsed
|
||||
simulatedTime = startTime + 10500; // TASK_ACCEL and TASK_ATTITUDE desiredPeriodUss have elapsed
|
||||
// of the two TASK_ACCEL should run first
|
||||
scheduler();
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
// and finally TASK_ATTITUDE should now run
|
||||
scheduler();
|
||||
EXPECT_EQ(&cfTasks[TASK_ATTITUDE], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ATTITUDE], unittest_scheduler_selectedTask);
|
||||
}
|
||||
|
||||
TEST(SchedulerUnittest, TestGyroTask)
|
||||
|
@ -426,7 +431,7 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
|
||||
// disable all tasks except TASK_GYRO, TASK_FILTER and TASK_PID
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
||||
setTaskEnabled(static_cast<taskId_e>(taskId), false);
|
||||
}
|
||||
setTaskEnabled(TASK_GYRO, true);
|
||||
setTaskEnabled(TASK_FILTER, true);
|
||||
|
@ -434,14 +439,14 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
|
||||
// First set it up so TASK_GYRO just ran
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime;
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime;
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
||||
// run the scheduler
|
||||
scheduler();
|
||||
// no tasks should have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
// also the gyro, filter and PID task indicators should be false
|
||||
EXPECT_FALSE(taskGyroRan);
|
||||
EXPECT_FALSE(taskFilterRan);
|
||||
|
@ -450,7 +455,7 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
/* Test the gyro task running but not triggering the filtering or PID */
|
||||
// set the TASK_GYRO last executed time to be one period earlier
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
@ -462,12 +467,12 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
EXPECT_FALSE(taskFilterRan);
|
||||
EXPECT_FALSE(taskPidRan);
|
||||
// expect that no other tasks other than TASK_GYRO should have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
|
||||
/* Test the gyro task running and triggering the filtering task */
|
||||
// set the TASK_GYRO last executed time to be one period earlier
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
@ -480,12 +485,12 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
EXPECT_TRUE(taskFilterRan);
|
||||
EXPECT_FALSE(taskPidRan);
|
||||
// expect that no other tasks other tasks should have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
|
||||
/* Test the gyro task running and triggering the PID task */
|
||||
// set the TASK_GYRO last executed time to be one period earlier
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
@ -498,7 +503,7 @@ TEST(SchedulerUnittest, TestGyroTask)
|
|||
EXPECT_FALSE(taskFilterRan);
|
||||
EXPECT_TRUE(taskPidRan);
|
||||
// expect that no other tasks other tasks should have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
}
|
||||
|
||||
// Test the scheduling logic that prevents other tasks from running if they
|
||||
|
@ -518,21 +523,21 @@ TEST(SchedulerUnittest, TestGyroLookahead)
|
|||
|
||||
// disable all tasks except TASK_GYRO, TASK_ACCEL
|
||||
for (int taskId = 0; taskId < TASK_COUNT; ++taskId) {
|
||||
setTaskEnabled(static_cast<cfTaskId_e>(taskId), false);
|
||||
setTaskEnabled(static_cast<taskId_e>(taskId), false);
|
||||
}
|
||||
setTaskEnabled(TASK_GYRO, true);
|
||||
setTaskEnabled(TASK_ACCEL, true);
|
||||
|
||||
#if defined(USE_TASK_STATISTICS)
|
||||
// set the average run time for TASK_ACCEL
|
||||
cfTasks[TASK_ACCEL].movingSumExecutionTime = TEST_UPDATE_ACCEL_TIME * TASK_STATS_MOVING_SUM_COUNT;
|
||||
tasks[TASK_ACCEL].movingSumExecutionTimeUs = TEST_UPDATE_ACCEL_TIME * TASK_STATS_MOVING_SUM_COUNT;
|
||||
#endif
|
||||
|
||||
/* Test that another task will run if there's plenty of time till the next gyro sample time */
|
||||
// set it up so TASK_GYRO just ran and TASK_ACCEL is ready to run
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime;
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime;
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
||||
|
@ -543,13 +548,13 @@ TEST(SchedulerUnittest, TestGyroLookahead)
|
|||
EXPECT_FALSE(taskFilterRan);
|
||||
EXPECT_FALSE(taskPidRan);
|
||||
// TASK_ACCEL should have run
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
|
||||
/* Test that another task won't run if the time till the gyro task is less than the guard interval */
|
||||
// set it up so TASK_GYRO will run soon and TASK_ACCEL is ready to run
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ) + GYRO_TASK_GUARD_INTERVAL_US / 2;
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ) + GYRO_TASK_GUARD_INTERVAL_US / 2;
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
||||
|
@ -560,13 +565,13 @@ TEST(SchedulerUnittest, TestGyroLookahead)
|
|||
EXPECT_FALSE(taskFilterRan);
|
||||
EXPECT_FALSE(taskPidRan);
|
||||
// TASK_ACCEL should not have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
|
||||
/* Test that another task won't run if the time till the gyro task is less than the average task interval */
|
||||
// set it up so TASK_GYRO will run soon and TASK_ACCEL is ready to run
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ) + TEST_UPDATE_ACCEL_TIME / 2;
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ) + TEST_UPDATE_ACCEL_TIME / 2;
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
||||
|
@ -577,13 +582,13 @@ TEST(SchedulerUnittest, TestGyroLookahead)
|
|||
EXPECT_FALSE(taskFilterRan);
|
||||
EXPECT_FALSE(taskPidRan);
|
||||
// TASK_ACCEL should not have run
|
||||
EXPECT_EQ(static_cast<cfTask_t*>(0), unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(static_cast<task_t*>(0), unittest_scheduler_selectedTask);
|
||||
|
||||
/* Test that another task will run if the gyro task gets executed */
|
||||
// set it up so TASK_GYRO will run now and TASK_ACCEL is ready to run
|
||||
simulatedTime = startTime;
|
||||
cfTasks[TASK_GYRO].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
cfTasks[TASK_ACCEL].lastExecutedAt = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
tasks[TASK_GYRO].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(TEST_GYRO_SAMPLE_HZ);
|
||||
tasks[TASK_ACCEL].lastExecutedAtUs = simulatedTime - TASK_PERIOD_HZ(1000);
|
||||
// reset the flags
|
||||
resetGyroTaskTestFlags();
|
||||
|
||||
|
@ -598,5 +603,5 @@ TEST(SchedulerUnittest, TestGyroLookahead)
|
|||
EXPECT_TRUE(taskFilterRan);
|
||||
EXPECT_TRUE(taskPidRan);
|
||||
// TASK_ACCEL should have run
|
||||
EXPECT_EQ(&cfTasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
EXPECT_EQ(&tasks[TASK_ACCEL], unittest_scheduler_selectedTask);
|
||||
}
|
||||
|
|
|
@ -160,6 +160,6 @@ void beeper(beeperMode_e) {}
|
|||
uint8_t detectedSensors[] = { GYRO_NONE, ACC_NONE };
|
||||
timeDelta_t getGyroUpdateRate(void) {return gyro.targetLooptime;}
|
||||
void sensorsSet(uint32_t) {}
|
||||
void schedulerResetTaskStatistics(cfTaskId_e) {}
|
||||
void schedulerResetTaskStatistics(taskId_e) {}
|
||||
int getArmingDisableFlags(void) {return 0;}
|
||||
}
|
||||
|
|
|
@ -154,10 +154,10 @@ static bool portIsShared = false;
|
|||
static bool openSerial_called = false;
|
||||
static bool telemetryDetermineEnabledState_stub_retval;
|
||||
|
||||
void rescheduleTask(cfTaskId_e taskId, uint32_t newPeriodMicros)
|
||||
void rescheduleTask(taskId_e taskId, timeDelta_t newPeriodUs)
|
||||
{
|
||||
EXPECT_EQ(TASK_TELEMETRY, taskId);
|
||||
EXPECT_EQ(1000, newPeriodMicros);
|
||||
EXPECT_EQ(1000, newPeriodUs);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -143,7 +143,7 @@ extern "C" {
|
|||
bool calculateRxChannelsAndUpdateFailsafe(timeUs_t) { return true; }
|
||||
bool isMixerUsingServos(void) { return false; }
|
||||
void gyroUpdate() {}
|
||||
timeDelta_t getTaskDeltaTime(cfTaskId_e) { return 0; }
|
||||
timeDelta_t getTaskDeltaTimeUs(taskId_e) { return 0; }
|
||||
void updateRSSI(timeUs_t) {}
|
||||
bool failsafeIsMonitoring(void) { return false; }
|
||||
void failsafeStartMonitoring(void) {}
|
||||
|
@ -173,7 +173,7 @@ extern "C" {
|
|||
void dashboardEnablePageCycling(void) {}
|
||||
void dashboardDisablePageCycling(void) {}
|
||||
bool imuQuaternionHeadfreeOffsetSet(void) { return true; }
|
||||
void rescheduleTask(cfTaskId_e, uint32_t) {}
|
||||
void rescheduleTask(taskId_e, timeDelta_t) {}
|
||||
bool usbCableIsInserted(void) { return false; }
|
||||
bool usbVcpIsConnected(void) { return false; }
|
||||
void pidSetAntiGravityState(bool newState) { UNUSED(newState); }
|
||||
|
@ -188,4 +188,5 @@ extern "C" {
|
|||
void gyroFiltering(timeUs_t) {};
|
||||
timeDelta_t rxGetFrameDelta(timeDelta_t *) { return 0; }
|
||||
void updateRcRefreshRate(timeUs_t) {};
|
||||
uint16_t getAverageSystemLoadPercent(void) { return 0; }
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue