【FreeRTOS】02 任务的创建

上一节我们利用cubemx自动生成了一个实例,它建立了两个用户任务和一个默认任务,并成功运行起来了。本节我们将分析一下FreeRTOS任务创建的过程,并结合创建时需要的参数讲解一下FreeRTOS任务的一些特性。

使用的工程文件仍然是上一节生成的代码。

1)FreeRTOS创建任务的API

FreeRTOS提供了一套API函数,我们调用它的函数即可创建任务。

基本的创建任务函数有两个:xTaskCreatexTaskCreateStatic

xTaskCreate函数是用动态的方法创建一个任务,而xTaskCreateStatic函数用静态的方法创建任务;使用xTaskCreate创建任务时,系统自动为任务分配内存;而使用xTaskCreateStatic创建任务时,需要用户指定内存地址。

我们看一下它们的函数原型,首先是xTaskCreate

各参数的含义解释如下:

pxTaskCode:任务函数的入口,是一个函数指针,指向要执行的任务;

pcName:任务名称,是一个字符串;

usStackDepth:任务堆栈大小,注意实际申请的堆栈是usStackDepth个4字节空间;

pvParameters:传递给任务函数的参数;

uxPriotiry:任务优先级,范围0~configMAX_PRIORITIES-1;

pxCreatedTask:任务句柄,任务创建成功以后会返回此任务的句柄,这个句柄其实就是任务的任务堆栈地址;

xTaskCreateStatic函数的参数与xTaskCreate差不多,区别是最后两个参数:

最后两个参数的含义是:

puxStackBuffer:用户指定的这块内存地址,作为任务堆栈地址;

pxTaskBuffer:用户指定的这块内存地址,作为任务控制块。

2)cubemx生成的代码分析

了解了FreeRTOS创建任务的API函数,我们再来看看cubemx生成的代码是如何使用的。我们从main函数开始看。

打开工程文件的main函数,我们发现,与无操作系统的不同之处,是在硬件初始化之后、while(1)之前多了MX_FREERTOS_Init();和osKernelStart();两个函数。

MX_FREERTOS_Init就是操作系统初始化函数,我们跳转到它内部,创建了三个任务:

osThreadDef是一个宏,它的定义如下:

例如第114行的osThreadDef(myTask02, StartTask02, osPriorityHigh, 0, 128);这句,宏展开之后就是:

(还记得以前讲过的C语言宏定义#和##的用法吗?)

实际上,这一句就是定义了一个结构体变量os_thread_def_myTask02,并给它赋了初值。

然后,用osThreadCreate这个函数进行了任务创建。

它的第一个参数也是个宏,找到宏定义:

例如第115行的myTask02Handle = osThreadCreate(osThread(myTask02), NULL);将宏展开后,就是:

myTask02Handle = osThreadCreate(&os_thread_def_myTask02, NULL);

可以看到,第一个参数实际上就是我们前面定义的那个结构体os_thread_def_myTask02的指针。

继续深入,看看osThreadCreate这个函数到底干了啥。

osThreadCreate的代码比冗长,但是实际上,它只干了一件事,依据configSUPPORT_STATIC_ALLOCATION和configSUPPORT_DYNAMIC_ALLOCATION这两个宏定义的值,来选择调用freeRTOS的API函数 xTaskCreatexTaskCreateStatic 创建任务。

结合传入的参数,由于结构体os_thread_def_myTask02的最后两个参数初始化为NULL(没有指定内存地址),osThreadCreate内部调用了动态创建函数。任务的堆栈大小都是128*4字节。

至此,我们的三个任务创建成功。

这里说明一下这两个宏:

configSUPPORT_STATIC_ALLOCATION定义为1可以使用静态内存分配;

configSUPPORT_DYNAMIC_ALLOCATION定义为1可以使用动态内存分配。

这里两个宏在FreeRTOSConfig.h文件中(实际上freeRTOS的还有很多其他配置宏在这个文件中,以后涉及到了会详细讲解)。

在MX_FREERTOS_Init();函数中创建完三个任务,就进入函数osKernelStart();这个也是调用了一个freeROTS的API函数vTaskStartScheduler,用于启动任务调度。这里如果我们只关注应用,暂时不研究操作系统内部怎么执行任务的,不必深究。

3)创建任务测试

上一节中Cubemx生成的工程代码,是我们在图形界面下创建的几个任务;经过上面的讲解,我们掌握了freeROTS的API函数后,完全可以自己直接编写创建任务的函数。

这里,我们在原工程中添加一个任务,用直接用API函数创建任务。

我们使用静态方式,创建一个低优先级的任务,代码如下,先添加几个定义:

然后定义任务函数,就是一个无限循环,里面只是延时一下,其他什么也不干:

最后在MX_FREERTOS_Init函数中添加代码,创建Task04:

注意,这里我们使用的是静态创建的API函数xTaskCreateStatic

这样,我们就定义好了一个自己的任务,可以测试了。

编译,下载到开发板,我们在调试模式下测试,执行时分别在各个任务内设置断点,可以看到均能执行到断点处:

说明我们新添加的任务可以成功执行,也不影响其他任务的执行。

4)任务优先级测试

接下来我们修改一下代码,测试任务的优先级,由于我们新添加的Task04设置了优先级为(1)。如果有其他较高优先级的任务一直占用CPU,就不会执行到Task04。

查看宏定义,defaultTask的优先级osPriorityNormal定义是0,注意osThreadCreate在执行时做了一次变换,优先级变成了0-(-3)=3,比Task04要高。为此,我们把defaultTask任务里的延时去掉,让他一直占用CPU,另外添加一个变量自加语句,以方便设置断点观察。

再次编译,下载,进入调试模式运行,可以发现defaultTask的任务可以进入:

而Task04任务再也进入不了了,而且Task04任务里的j也不会增加。

而此时,如果在高优先级的Task02和Task03中设置断点,也是可以进入的:

这个实例说明,freeRTOS会执行优先级高的任务。只有高优先级的任务主动放弃执行(如执行到代码里的osDelay(xx),就会释放CPU x x毫秒),才会轮到低优先级的任务执行。

好了,本节的内容就到这里了。

如果觉得有用可以关注作者微信号“小白白学电子”,在公众号可以找到代码和资料下载地址:

  • 18
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值