目录
1.是否抢占优先级configUSE_PREEMPTION
2. 是否进行时间片轮转configUSE_TIME_SLICING
3. 空闲函数是否礼让configIDLE_SHOULD_YIELD
4. 实验
5. 特殊情况
在FreeRTOS中,Tick中断来执行任务调度,所谓的Tick中断,就是程序每执行固定时间后系统会发生定时器中断。
怎么来管理处于不同状态的任务?将不同状态的任务放在不同的链表内,等待态放在DelayList,暂停态放在SuspendedList,就绪态的任务放在ReadyList,就绪态的任务有5个优先级。当任务需要从就绪态转换为运行态的时候,先找到就绪态中最高优先级的任务运行。如果同一优先级的话就轮流执行,然后每个任务执行一个tick后排在链表最后面。
任务调度算法需要查看FreeRTOSConfig.h文件
1.是否抢占优先级
configUSE_PREEMPTION 当高优先级的任务处于就绪状态时,是否可以抢占优先级,打断低优先级任务的执行
设置为1则允许抢占优先级,设置0则不允许抢占优先级
2.是否进行时间片轮转
configUSE_TIME_SLICING 同等优先级的任务是否具有轮流执行的功能,如果不进行配置的话,当某个任务获得执行权之后在该任务结束之前会一直执行
设置为1则允许进行时间片轮转,设置0则不允许进行时间片轮转
3.空闲任务是否让步
configIDLE_SHOULD_YIELD 空闲任务是否具有礼让其他任务的功能,如果有同是优先级为0的其他就绪任务,空闲任务获取运行资格后,只运行一遍进行礼让,而其他任务运行一个tick周期
设置为1则空闲任务让步,设置0则空闲任务不让步
4.实验
任务1和空闲任务的优先级为0,任务2的优先级为2,程序如下:
static void prvSetupHardware( void );
static int task1flag=0;
static int task2flag=0;
static int taskIdleflag=0;
void Task1Function(void *param)
{
while(1)
{
task1flag=1;
task2flag=0;
taskIdleflag=0;
printf("1");
}
}
void Task2Function(void *param)
{
while(1)
{
task1flag=0;
task2flag=1;
taskIdleflag=0;
printf("2");
vTaskDelay(2);
}
}
void vApplicationIdleHook(void)
{
task1flag=0;
task2flag=0;
taskIdleflag=1;
printf("0");
}
StackType_t xIdleTaskStack[100];
StaticTask_t xIdelTaskTCB;
void vApplicationGetIdleTaskMemory(StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer=&xIdelTaskTCB;
*ppxIdleTaskStackBuffer=xIdleTaskStack;
*pulIdleTaskStackSize=100;
}
int main( void )
{
TaskHandle_t xHandleTask1;
prvSetupHardware();
printf("Hello World!\r\n");
xTaskCreate(Task1Function,"Task1",100,NULL,0,&xHandleTask1);
xTaskCreate(Task2Function,"Task2",100,NULL,2,NULL);
/* Start the scheduler. */
vTaskStartScheduler();
return 0;
}
实验一:
configUSE_PREEMPTION=0, configUSE_TIME_SLICING=0,configIDLE_SHOULD_YIELD=0不允许抢占优先级,不允许时间片轮转,不允许空闲函数礼让。代码显示,当不抢占的时候,空闲任务永远礼让,虽然配置了不礼让,但只要不抢占就礼让
任务2优先级最高先执行,执行之后进入阻塞状态,然后任务1开始执行,由于不允许抢占优先级,也不允许时间片轮转,则任务1一直执行,结果如下:
实验二:
configUSE_PREEMPTION=1, configUSE_TIME_SLICING=0,configIDLE_SHOULD_YIELD=0允许抢占优先级,不允许时间片轮转,不允许空闲函数礼让
任务2任务2优先级最高先执行,执行之后进入阻塞两个tick状态,然后任务1开始执行;任务2再次进入运行状态,抢占优先级,执行之后进入阻塞两个tick状态,然后空闲任务开始执行;循环上面的过程,结果如下:
实验三:
configUSE_PREEMPTION=1, configUSE_TIME_SLICING=1,configIDLE_SHOULD_YIELD=0允许抢占优先级,允许时间片轮转,不允许空闲函数礼让
任务2优先级最高先执行,执行之后进入阻塞两个tick状态,然后任务1和空闲任务进行时间片轮转,任务2再次进入运行状态,重复上面过程,结果如下:
实验四:
configUSE_PREEMPTION=1, configUSE_TIME_SLICING=0,configIDLE_SHOULD_YIELD=1允许抢占优先级,不允许时间片轮转,允许空闲函数礼让
任务2优先级最高先执行,执行之后进入阻塞两个tick状态,任务1执行;任务2再次执行,再次阻塞,然后空闲任务执行一次,马上礼让task1运行,循环伤处操作,结果如下:
实验五:
configUSE_PREEMPTION=1, configUSE_TIME_SLICING=1,configIDLE_SHOULD_YIELD=1允许抢占优先级,允许时间片轮转,允许空闲函数礼让
5.特殊情况
1.当任务1,任务2和空闲任务的优先级都为0时,如果先创建任务1,再创建任务2,启动调度器时会创建空闲任务,则任务执行时,先执行任务1,在执行任务2,再执行空闲任务。
2.当任务1,任务2的优先级为1,空闲任务的优先级都为0时,如果先创建任务1,再创建任务2,启动调度器时会创建空闲任务,则任务执行时,先执行任务2,在执行任务1。
原因:如果后创建任务的优先级大于等于当前任务的优先级,则当前TCB指向后创建的任务,然后任务按顺序执行