FreeRTOS的创建
基于keil5软件:
要包含 #include "FreeRTOS.h"和#include "task.h"这两个头文件,我们在创建一些任务的时候需要这两个头文件。
FreeRTOS要求我们用中断优先级分组4,支持16级的抢占优先级。
FreeRTOS中任务的最高优先级是通过FreeRTOSConfig.h中的configMAX_PRIORITIES 进行配置的,用户实际可以使用的优先级范围是0- configMAX_PRIORITIES -1,也就是说设置的优先级是3,那么我们可以使用的优先级号就是0,1,2不包含3,数字越大优先级越高。
那么我们如何创建任务 ?
这时我们需要用到一个函数xTaskCreate,这个函数和线程函数pthread_create非常相似,功能是差不多的,只不过xTaskCreate里面的参数和pthread_create不一样,接下来让我们看一下如何去写这个函数。
创建任务后我们要开启任务调度
vTaskStartScheduler();
函数代码编写如下:
/*
第一个参数表示线程函数
第二个参数表示任务名字,自定义
第三个参数表示任务的栈空间,给多少空间
第四个参数表示参数传递,不传就写空
第五个参数表示表示优先级
第六个参数表示句柄等同于线程ID
*/
xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);
//这里我们就顺手写一下根据上面的任务所创建的函数
void app_task1(void *pvParameters)
{
while(1)
{
//睡眠延时1000ms
vTaskDelay(1000);
printf("[app_task1] runing .....");
}
}
注意,RTOS总是运行优先级最高且就绪的任务
如果我们将睡眠延时改成10ms,我们就会发现,低优先级的任务会被抢占,任务被抢占后会从运行态转变为就绪态。如下例子
//我们创建两个任务
int main()
{
xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);
xTaskCreate(app_task2,"app_task2",512,NULL,7,&app_task2_handle);
vTaskStartScheduler();
while(1)
{
}
}
void app_task1(void *pvParameters)
{
while(1)
{
printf("[app_task1] runing .....");
//睡眠延时10ms
vTaskDelay(10);
}
}
void app_task2(void *pvParameters)
{
while(1)
{
printf("[app_task2] runing .....");
//睡眠延时10ms
vTaskDelay(10);
}
}
根据上面代码我们可以得知,任务2的优先级比任务1要高,这里的优先级是数字越小优先级越低,这里会先执行任务2,执行后任务2由运行态变为阻塞态,任务1由就绪态变为运行态,此时任务2经过10ms延时之后从阻塞态变为就绪态且任务2的优先级比任务1高,任务1就从运行态变为就绪态,任务2从就绪态变为运行态,后面以此类推,看下图更好理解。
通过图片我们可以看到第一行任务2是正常运行,第二行开始,任务1在运行时被任务2抢占,此时任务1就变成了就绪状态,第三行也是一样,被任务2抢占,第四行也是同理,这也就导致了任务2完整执行4次,而任务1只完整执行1次,那么我们该如何解决这类问题呢?我们可以通过挂起任务2来让任务1完整运行,如下代码所示
//我们一样创建两个任务
int main()
{
xTaskCreate(app_task1,"app_task1",512,NULL,6,&app_task1_handle);
xTaskCreate(app_task2,"app_task2",512,NULL,7,&app_task2_handle);
vTaskStartScheduler();
while(1)
{
}
}
void app_task1(void *pvParameters)
{
while(1)
{
vTaskSuspend(app_task2_handle);//挂起任务2
printf("[app_task1] runing .....");
vTaskResume(app_task2_handle);//取消挂起
//睡眠延时10ms
vTaskDelay(10);
}
}
void app_task2(void *pvParameters)
{
while(1)
{
printf("[app_task2] runing .....");
//睡眠延时10ms
vTaskDelay(10);
}
}
可以看到我们用了一个vTaskSuspend()函数,这个函数就是用来挂起某个任务,里面的参数就是你要挂起的任务句柄,句柄就是你创建任务时最后的那个参数,带&符号的那个,当我们挂起这个任务时要记住取消挂起。取消挂起函数vTaskResume(),参数和挂起函数是一样的,此时我们再看下结果。
此时就是正常的