一.任务状态理论讲解
正在执行的任务状态是running,其他执行的等待执行的任务状态是ready
1.修改间隔时间
2.任务状态
处于各个状态的任务是怎样被管理起来的:链表
3.代码
TaskHandle_t xHandleTask1;
TaskHandle_t xHandleTask3;
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;
void Task1Function(void * param)
{
TickType_t tStart = xTaskGetTickCount();
TickType_t t;
int flag = 0;
while (1)
{
t = xTaskGetTickCount();
task1flagrun = 1;
task2flagrun = 0;
task3flagrun = 0;
printf("1");
if (!flag && (t > tStart + 10))
{
vTaskSuspend(xHandleTask3);
flag = 1;
}
if (t > tStart + 20)
{
vTaskResume(xHandleTask3);
}
}
}
void Task2Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 1;
task3flagrun = 0;
printf("2");
vTaskDelay(10);
}
}
void Task3Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 0;
task3flagrun = 1;
printf("3");
}
}
/*-----------------------------------------------------------*/
StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;
/*
* The buffers used here have been successfully allocated before (global variables)
*/
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = xIdleTaskStack;
*pulIdleTaskStackSize = 100;
}
int main( void )
{
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xHandleTask3 = xTaskCreateStatic(Task3Function, "Task3", 100, NULL, 1, xTask3Stack, &xTask3TCB);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
二.vTaskDelay和vTaskDelayUntil
vTaskDelay:至少等待指定个数的Tick Interrupt才能变为就绪状态
xTaskDelayUntil
-
返回pdTRUE表示确实延迟了,返回pdFALSE表示没有发生延迟(因为延迟的时间点早就过了)
-
等待到指定的绝对时刻,才能变为就绪态。
代码1 vTaskDelay
TaskHandle_t xHandleTask1;
TaskHandle_t xHandleTask3;
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;
static int rands[]={3,56,23,5,59};
void Task1Function(void * param)
{
TickType_t tStart = xTaskGetTickCount();
int i=0;
int j=0;
while (1)
{
task1flagrun = 1;
task2flagrun = 0;
task3flagrun = 0;
for( i= 0; i < rands[j] ; i++)
printf("1");
j++;
if ( j == 5)j = 0;
vTaskDelay(20);
}
}
void Task2Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 1;
task3flagrun = 0;
printf("2");
}
}
void Task3Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 0;
task3flagrun = 1;
printf("3");
}
}
/*-----------------------------------------------------------*/
StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;
/*
* The buffers used here have been successfully allocated before (global variables)
*/
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = xIdleTaskStack;
*pulIdleTaskStackSize = 100;
}
int main( void )
{
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 100, NULL, 2, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xHandleTask3 = xTaskCreateStatic(Task3Function, "Task3", 100, NULL, 1, xTask3Stack, &xTask3TCB);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
可以看到任务1执行的时间不一样,但是进入delay休眠的时间是一样的,都是20ms。
代码2 vTaskDelayUntil
BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
const TickType_t xTimeIncrement ) ;
// 1 延迟直到 *pxPre+xTime
// 2 *pxPre=*pxPre+xTime
TaskHandle_t xHandleTask1;
TaskHandle_t xHandleTask3;
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;
static int rands[]={3,56,23,5,59};
void Task1Function(void * param)
{
TickType_t tStart = xTaskGetTickCount();
int i=0;
int j=0;
while (1)
{
task1flagrun = 1;
task2flagrun = 0;
task3flagrun = 0;
for( i= 0; i < rands[j] ; i++)
printf("1");
j++;
if ( j == 5)j = 0;
#if 0
vTaskDelay(20);
#else
xTaskDelayUntil(&tStart,20);
#endif
}
}
void Task2Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 1;
task3flagrun = 0;
printf("2");
}
}
void Task3Function(void * param)
{
while (1)
{
task1flagrun = 0;
task2flagrun = 0;
task3flagrun = 1;
printf("3");
}
}
/*-----------------------------------------------------------*/
StackType_t xTask3Stack[100];
StaticTask_t xTask3TCB;
StackType_t xIdleTaskStack[100];
StaticTask_t xIdleTaskTCB;
/*
* The buffers used here have been successfully allocated before (global variables)
*/
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
StackType_t ** ppxIdleTaskStackBuffer,
uint32_t * pulIdleTaskStackSize )
{
*ppxIdleTaskTCBBuffer = &xIdleTaskTCB;
*ppxIdleTaskStackBuffer = xIdleTaskStack;
*pulIdleTaskStackSize = 100;
}
int main( void )
{
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 100, NULL, 2, &xHandleTask1);
xTaskCreate(Task2Function, "Task2", 100, NULL, 1, NULL);
xHandleTask3 = xTaskCreateStatic(Task3Function, "Task3", 100, NULL, 1, xTask3Stack, &xTask3TCB);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
以每20ms周期性的执行
三.空闲任务及钩子函数
实验1
执行任务1,任务1的任务是创建任务2,当任务2创建成功,任务2的优先级更高,直接执行任务2。任务2的任务是打印一个2,然后进入阻塞,任务1运行删除任务。
extern void Task2Function(void * param);
void Task1Function(void * param)
{
TaskHandle_t xHandleTask2;
BaseType_t xReturn;
while (1)
{
printf("1");
xReturn=xTaskCreate(Task2Function, "Task2", 1024, NULL, 2, &xHandleTask2);
if(xReturn!=pdPASS)
{
printf("xTaskCreate err\r\n");
}
vTaskDelete(xHandleTask2);
}
}
void Task2Function(void * param)
{
while (1)
{
printf("2");
vTaskDelay(2);
}
}
/*-----------------------------------------------------------*/
int main( void )
{
TaskHandle_t xHandleTask1;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
并没有执行我们想要的清理工作。
我们进行的清理工作(内存回收工作)是放在空闲任务里面的。
实验2
执行自杀操作
extern void Task2Function(void * param);
void Task1Function(void * param)
{
TaskHandle_t xHandleTask2;
BaseType_t xReturn;
while (1)
{
printf("1");
xReturn=xTaskCreate(Task2Function, "Task2", 1024, NULL, 2, &xHandleTask2);
if(xReturn!=pdPASS)
{
printf("xTaskCreate err\r\n");
}
//vTaskDelete(xHandleTask2);
}
}
void Task2Function(void * param)
{
while (1)
{
printf("2");
vTaskDelay(2);
vTaskDelete(NULL);//执行自杀操作
}
}
/*-----------------------------------------------------------*/
int main( void )
{
TaskHandle_t xHandleTask1;
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 100, NULL, 1, &xHandleTask1);
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
执行自杀操作应该由空闲任务帮你执行清理工作
配置钩子函数
在main函数里面创建任务1,优先级是0,任务1里面创建任务2,任务2优先级更高执行完之后就自杀。之后任务1和任务0可以交替执行
四.任务调度算法
static int task1flagrun = 0;
static int task2flagrun = 0;
static int task3flagrun = 0;
static int taskidleflagrun = 0;
void Task1Function(void * param)
{
//volatile char buf[500];
//int i;
while (1)
{
task1flagrun = 1;
task2flagrun = 0;
task3flagrun = 0;
taskidleflagrun = 0;
printf("1");
}
}
void Task2Function(void * param)
{
int i = 0;
while (1)
{
task1flagrun = 0;
task2flagrun = 1;
task3flagrun = 0;
taskidleflagrun = 0;
printf("2");
}
}
void Task3Function(void * param)
{
const TickType_t xDelay5ms=pdMS_TO_TICKS(5UL);
while (1)
{
task1flagrun = 0;
task2flagrun = 0;
task3flagrun = 1;
taskidleflagrun=0;
printf("3");
//如果不休眠的化,其他任务无法得到执行
vTaskDelay(xDelay5ms);
}
}
void vApplicationIdleHook()
{
task1flagrun = 0;
task2flagrun = 0;
task3flagrun = 0;
taskidleflagrun=1;
}
int main( void )
{
#ifdef DEBUG
debug();
#endif
prvSetupHardware();
printf("Hello, world!\r\n");
xTaskCreate(Task1Function, "Task1", 1000, NULL, 0, NULL);
xTaskCreate(Task2Function, "Task2", 1000, NULL, 0, NULL);
xTaskCreate(Task3Function, "Task3", 1000, NULL, 2, NULL);
//优先级最高的任务3先执行
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was not enough heap space to create the
idle task. */
return 0;
}
1.可以抢占
这个宏定义是否可以抢占
任务3优先级最高,先执行执行完阻塞5ms,其他任务执行。执行任务1,任务2,任务1,任务2,任务0,任务1。5ms到了立刻执行任务3...
A.时间片轮转
任务3优先级最高,先执行执行完阻塞5ms,其他任务执行。执行任务1,任务2,任务1,任务2,任务0,任务1。5ms到了立刻执行任务3...
B.时间片不轮转
任务3优先级最高先执行,执行完进入休眠,任务1执行直到任务3休眠结束,任务3执行结束,就接着让任务2执行....
2.不可以抢占
任务3执行完了进入阻塞,任务1一直执行。如果需要让出CPU资源还是需要自己去主动进入休眠。
3.空闲任务是否让步于用户任务