RTOS理论基础知识快速入门
一、RTOS与裸机的区别
裸机: 裸机又称为前后台系统,前台系统指的中断服务函数,后台系统指的大循环,即应用程序
- 实时性差:(应用程序)轮流执行
- delay:空等待,CPU不执行其他代码
- 结构臃肿:实现功能都放在无限循环
RTOS特点: RTOS全称为:Real Time OS,就是实时操作系统,强调的是:实时性
- 分而治之:实现功能划分为多个任务
- 延时函数:任务调度
- 抢占式:高优先级任务抢占低优先级任务
- 任务堆栈:每个任务都有自己的栈空间
注意: - 中断可以打断任意任务
- 任务可以同等优先
RTOS实现多任务的原理:
- 严格来说 FreeRTOS 并不是实时操作系统,因为它是分时复用的。
- 系统将时间分割成很多时间片,然后轮流执行各个任务。
- 每个任务都是独立运行的,互不影响,由于切换的频率很快,就感觉像是同时运行的一样。
二、任务的创建与删除
1. 什么是任务?
- 任务可以理解为进程/线程,创建一个任务,就会在内存开辟一个空间。
- 比如:玩游戏、陪女朋友,都可以视为任务
- Windows 系统中的 MarkText 、谷歌浏览器、记事本,都是任务。
- 任务通常都含有 while(1) 死循环。
2. 任务创建与删除相关函数
任务创建与删除相关函数有如下三个:
函数名称 | 函数作用 |
---|---|
xTaskCreate() | 以动态的方式创建任务(常用) |
xTaskCreateStatic() | 以静态的方式创建任务(不常用) |
vTaskDelete() | 删除任务(不太常用) |
任务动态创建与静态创建的区别:
动态创建任务的堆栈由系统分配,而静态创建任务的堆栈由用户自己传递。通常情况下使用动态方式创建任务。
xTaskCreate 函数原型
BaseType_t xTaskCreate
(
TaskFunction_t pxTaskCode, //指向任务函数的指针(任务函数名)
const char * const pcName, //任务名称,最大长度宏configMAX_TASK_NAME_LEN,长为16
const configSTACK_DEPTH_TYPE usStackDepth, //任务堆栈大小,注意字为单位
void * const pvParameters, //传递给任务函数的参数,长为NULL
UBaseType_t uxPriority, //任务优先级,范围0 ~ configMAX_PRIORITIES-1
TaskHandle_t * const pxCreatedTask //任务句柄,就是任务的任务控制块
)
- pvTaskCode:指向任务函数的指针,任务必须实现为永不返回(即连续循环);
- pcName:任务的名字,主要是用来调试,默认情况下最大长度是16;
- pvParameters:指定的任务栈的大小;
- uxPriority:任务优先级,数值越大,优先级越大;
- pxCreatedTask:用于返回已创建任务的句柄可以被引用。
返回值:
返回值 | 描述 |
---|---|
pdPASS | 任务创建成功 |
errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY | 任务创建失败 |
官方案例:
/* Task to be created. */
void vTaskCode( void * pvParameters )
{
/* The parameter value is expected to be 1 as 1 is passed in the
pvParameters value in the call to xTaskCreate() below.*/
//configASSERT( ( ( uint32_t ) pvParameters ) == 1 );
for( ;; )
{
/* Task code goes here. */
}
}
/* Function that creates a task. */
void vOtherFunction( void )
{
BaseType_t xReturned;
TaskHandle_t xHandle = NULL;
/* Create the task, storing the handle. */
xReturned = xTaskCreate
(
vTaskCode, /* Function that implements the task. */
"NAME", /* Text name for the task. */
STACK_SIZE, /* Stack size in words, not bytes. */
( void * ) 1, /* Parameter passed into the task. */
tskIDLE_PRIORITY, /* Priority at which the task is created. */
&xHandle /* Used to pass out the created task's handle.*/
);
if( xReturned == pdPASS )
{
/* The task was created. Use the task's handle to delete the task. */
vTaskDelete( xHandle );
}
}
vTaskDelete 函数原型
void vTaskDelete(TaskHandle_t xTaskToDelete);
-
只需将待删除的任务句柄传入该函数,即可将该任务删除。
-
当传入的参数为NULL,则代表删除任务自身(当前正在运行的任务)。
-
一般无特殊情况,不做删除任务
三、任务调度
调度就是使用相关的调度算法来决定当前需要执行的哪个任务。FreeRTOS中开启任务调度的函数是vTaskStartScheduler()
,但在CubeMX 中被封装为osKernelStart()
1. FreeRTOS的任务调度规则
FreeRTOS 是一个实时操作系统,它所奉行的调度规则:
- 高优先级抢占低优先级任务,系统永远执行最高优先级的任务(即抢占式调度)
- 同等优先级的任务轮转调度(即时间片流转)
还有一种调度规则是协程式调度,但官方已明确表示不更新,主要是用在小容量的芯片上,用得也不多。
2. 抢占式调度运行过程
![](https://img-blog.csdnimg.cn/direct/e915b8e38b144876a9facad66847eba1.png)
Task 1:玩游戏
Task 2:老妈喊你吃饭
Task 3:女朋友喊你看电视
总结:
- 高优先级任务,优先执行;
- 高优先级任务不停止,低优先级任务无法执行;
- 被抢占的任务将会进入就绪态
3. 时间片调度运行过程
![](https://img-blog.csdnimg.cn/direct/64b102e95825498cbc3ff84446c83a4f.png)
总结:
- 同等优先级任务,轮流执行,时间片流转;
- 一个时间片大小,取决为滴答定时器中断周期;
- 注意没有用完的时间片不会再使用,下次任务 Task3 得到执行,还是按照一个时间片的时钟节拍运行
四、任务的状态
FreeRTOS中任务共存在4种状态:
- Running 运行态
当任务处于实际运行状态称之为运行态,即CPU的使用权被这个任务占用(同一时间仅一个任务处于运行态)。 - Ready 就绪态
处于就绪态的任务是指那些能够运行(没有被阻塞和挂起),但是当前没有运行的任务,因为同优先级或更高优先级的任务正在运行。 - Blocked 阻塞态
如果一个任务因延时,或等待信号量、消息队列、事件标志组等而处于的状态被称之为阻塞态。 - Suspended 挂起态
类似暂停,通过调用函数vTaskSuspend()
对指定任务进行挂起,挂起后这个任务将不被执行,只有调用函数xTaskResume()
才可以将这个任务从挂起态恢复。
![](https://img-blog.csdnimg.cn/direct/f780f18d64244f5b88b400975b64a8a8.png#pic_center)
注意:
- 仅就绪态可转变成运行态
- 其他状态的任务想运行,必须先转变成就绪态