STM32+FreeRTOS+CUBEMX_学习笔记(三)freertos官方文档分析,时间片调度和抢占式调度的区别
目录
一、前言和目的:
在使用freertos的过程中,难免会遇到关于任务优先级和时间片分配的问题。为了更好的使用该系统,学习了下面的一些知识。
- 看freertos源文档
- 时间片调度
- 抢占式调度
- 对比两种调度的方式
二、freertos文档:
2.0、看看源文档:
源文档是个好东西啊,虽然网上的论坛和帖子里面都存在很多的答案,但是任何转述的东西或者自己的语言都经过了一定的加工和改造。虽然可能会让人更加容易理解,但是终究是不如源文档的正式和官方。
以下为对源文档的学习和翻译:
2.1、freertos任务定义:
Tasks are implemented as C functions. The only thing special about them is their prototype,
which must return void and take a void pointer parameter.
freertos说任务就是一个c函数,唯一特殊的事情就是,他们必须返回一个空,然后必须有一个空指针参数。
Each task is a small program in its own right. It has an entry point, will normally run forever
within an infinite loop, and will not exit. The structure of a typical task is shown in Listing 12.
FreeRTOS tasks must not be allowed to return from their implementing function in any way—
they must not contain a ‘return’ statement and must not be allowed to execute past the end of
the function. If a task is no longer required, it should instead be explicitly deleted. This is also
demonstrated in Listing 12.
A single task function definition can be used to create any number of tasks—each created task
being a separate execution instance, with its own stack and its own copy of any automatic
(stack) variables defined within the task itself
每一个任务在他自己的范围内都是一个小程序,有一个进入指针,还会在它里面的一个循环中不断运行,不会退出。freertos任务一定不能有一个返回值。并且,不能包含return语句,同时不允许在函数结束时执行程序。如果这个任务不需要,它必须被完全删除。
一个任务定义可以被用来创建任意数量的任务,每一个被创建任务成为一个独立的执行项目,它们都有他们自己的自动变量在它们里面。
任务例子:
void ATaskFunction( void *pvParameters )
{
/* Variables can be declared just as per a normal function. Each instance of a task
created using this example function will have its own copy of the lVariableExample
variable. This would not be true if the variable was declared static – in which case
only one copy of the variable would exist, and this copy would be shared by each
created instance of the task. (The prefixes added to variable names are described in
section 1.5, Data Types and Coding Style Guide.) */
int32_t lVariableExample = 0;
/* A task will normally be implemented as an infinite loop. */
for( ;; )
{
/* The code to implement the task functionality will go here. */
}
/* Should the task implementation ever break out of the above loop, then the task
must be deleted before reaching the end of its implementing function. The NULL
parameter passed to the vTaskDelete() API function indicates that the task to be
deleted is the calling (this) task. The convention used to name API functions is
described in section 0, Projects that use a FreeRTOS version older than V9.0.0
must build one of the heap_n.c files. From FreeRTOS V9.0.0 a heap_n.c file is only
required if configSUPPORT_DYNAMIC_ALLOCATION is set to 1 in FreeRTOSConfig.h or if
configSUPPORT_DYNAMIC_ALLOCATION is left undefined. Refer to Chapter 2, Heap Memory
Management, for more information.
Data Types and Coding Style Guide. */
vTaskDelete( NULL );
}
2.1、freertos任务状态:
- frt的任务,在顶层只分为两种状态:运行和不运行。同时运行的数量取决于处理核心的数量。掌管任务间调度的工具是:FreeRTOS scheduler
三、freertos任务调度方式:
方式 | 内容 |
---|---|
合作 | 该功能在stm32中很少用到 |
抢占式调度 | 利用优先级顺序执行 |
时间片调度 | 利用分配的时间片进行调度 |
四、时间片方式:
- 时间片即人设的滴答时钟周期,例如滴答时钟频率如果设置为100HZ,那么一个滴答时钟周期就是10毫秒,一个时间片就运行一个10毫秒时间。
- 在同等优先级的情况下,被设置时间片时间的两个任务分别按照所设置的时间片运行对应的时间,然后切换至下一个任务。
- 在不同优先级下:因为在执行完任务之后,调度器总是会选择优先级比较高的任务来执行,所以如果两个任务时间片相同,任务优先级不同的话,那么优先级高的任务一直在执行,我们可以说低优先级的任务被高优先级的任务饿死了。
五、抢占式方式:
- 该方式,即每个任务执行完成之后执行已经就绪的任务优先级最高的那个。
- 说明一下,在不运行状态时吗,还可以分作几个状态
状态 | 内容 |
---|---|
挂起 | 我们可以使用函数挂起任务,然后这个任务再被取消挂起之前将一直得不到执行 |
就绪 | 该函数已经准备完毕,只等待调度器来执行这个函数 |
阻塞 | 当调用一些系统延时函数或者等待信号量等操作时,该任务阻塞。 |
六、对比:
1、 当采用相同优先级,使用相同时间片时:两个任务交替执行。
2、当采用不同优先级,使用相同时间片时:高优先级任务执行完自己的时间片之后,立即进入就绪状态,那么调度器又将进入这个任务。优先级较低的这个永远得不到执行。
七、总结:
方式 | 内容 |
---|---|
时间片调度 | 可以直接设置某个任务的执行时间,可以保证某个任务的执行长度,但是无法区分先后顺序 |
抢占式调度 | 可以保证高优先级的任务的执行,但是对于低优先级的保护不够。 |
- 在一般的项目中,为了任务的实时要求性,我们还是抢占式用的比较多。因为这样可以保证优先级高的任务可以得到快速的执行。但是问题也是存在的。如果优先级比较高的任务一直在执行的话,那么优先级的任务可能会被饿死。这样我们就必须采取一些措施,例如窗口看门狗来保证任务的执行。
- 但是,我们其实可以同时使用这个操作。在同一优先级的任务中采用时间片轮换。而将需要比较及时的任务放到更高的优先级中保证执行,充分利用两者的优点。