FreeRTOS任务管理与通信机制全解析
1.任务管理:
1)任务状态:
运行态可以转换到就绪态,阻塞态,挂起态。
就绪态可以转换到运行态,挂起态。
阻塞态可以转换到就绪态,挂起态。
挂起态可以转换到就绪态。
2)任务控制块TCB:
(1)任务函数的入口地址:任务函数的定义格式
void startTaskA(void* arg)
{
for(;;)
{
//写任务需要执行代码
//通常需要考虑进入到非运行态(释放CPU使用权)
}
vTaskDelete(NULL);
}
(2)任务名
(3)堆栈大小
(4)任务的优先级
3)任务的操作:
(1)任务的创建:xTaskCreate()
(2)任务的删除:vTaskDelete()
(3)任务挂起与解除挂起:vTaskSuspend(),vTaskResume()
(4)使任务休眠阻塞:vTaskDelay(),参数:表示需要休眠的节拍数
2.任务的通信
1)队列的用途:
实现任务之间的数据传递,队列实现任务间通信的基础。
2)队列的特点:
FIFO,先入先出
任务对队列操作可能引起阻塞;写阻塞,读阻塞
写队列会将数据拷贝写入到队列的末尾
读队列会从队列的头部读取并删除数据
创建时,需要指定队列的深度,以及数据块大小
1.创建队列:
QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize);
参数依次: 队列的深度, 队列中每个数据块的大小
返回值: 队列的句柄
2.发送消息:
BaseType_t xQueueSend(QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait);
参数依次: 队列句柄, 待发送数据的地址, 超时时间(若出现写阻塞)
3.从中断中发送消息
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t * pxHigherPriorityTaskWoken);
4.接收消息
BaseType_t xQueueReceive(QueueHandle_t xQueue, void * pvBuffer, TickType_t xTicksToWait);
参数依次: 队列句柄, 存储接收数据的地址, 超时时间(若出现读阻塞)
为什么上传数据到队列可能会超时?
A: 因为队列存在“写阻塞”特性,当一个任务对一个已经装满的队列进行写操作,
它就就会进入到阻塞状态,直到队列解除阻塞(通常是队列被读取了数据 或 队列被
删除)那么任务会回到就绪态 或 超时时间达到,写入失败
5.何时必须使用由TIM实现的定时函数?
当实现通信操作时,比如实现IIC通信的开始条件、停止条件、发送数据帧时。必须使用TIM的定时函数,若使用了vTaskDelay()则可能导致延时阻塞的期间执行了其他任务,最终使开始条件或停止条件中的某个时段延长,超出了规定时间,开始或停止条件建立失败。
3)信号量:实现任务之间同步
1.核心操作:
创建这种信号。
信号量P操作。 信号量-1,即公共资源数量减一。任务申请占用一个公共资源
(有两种结果:若当前有资源,成功占用;若当前没有资源,阻塞直到有资源)
信号量V操作。信号量+1,即公共资源数量加一。任务释放一个占用的公共资源。
没有优先级继承机制,不适合用于实现任务间的互斥;错误使用可能会出现“优先级反转问题”。
2.FreeRTOS中的信号量主要有两种类型:计数信号量和二值信号量。
二值信号量(Binary Semaphore)
概念:二值信号量是一种只有两个值(0和1)的特殊信号量。
作用:用于任务同步或事件通知,以及控制对某个资源的独占访问。例如,某任务等待中断事件触发,中断服务函数通过释放二值信号量通知任务。
特点:
- 轻量级:占用内存少,操作简单。
- 事件通知:适用于中断触发的事件处理。
- 二选一:只有两种状态(已释放/已获取),逻辑清晰。
- 功能单一:不能记录多个事件发生的情况。
- 没有优先级继承:可能发生优先级翻转问题。
创建信号量:
二值信号量:SemaphoreHandle_t xSemaphoreCreateBinary(void);
计数信号量:SemaphoreHandle_t xSemaphoreCreateCounting(UBaseType_t uxMaxCount, UBaseType_t uxInitialCount);
释放信号量/信号量+1:BaseType_t xSemaphoreGive(SemaphoreHandle_t xSemaphore);
(信号量的V操作)
从中断中释放信号量:BaseType_t xSemaphoreGiveFromISR(SemaphoreHandle_t xSemaphore, BaseType_t * pxHigherPriorityTaskWoken);
获取信号量/试图信号量-1:BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
(信号量的P操作)
4)互斥锁:实现任务之间互斥
优先级继承:
(1)触发前提:
两个优先级不同的任务竞争公共资源,低优先级任务先执行P操作抢占到资源,
高优先级任务后执行P操作去抢占资源。
(2)触发时机:
高优先级任务执行P操作,但资源已被低优先级任务占用,高优先级任务阻塞。
(3)效果:
在低优先级任务释放资源之前(V操作之前),低优先级任务会临时被系统自动提升优先级
直到与高优先级的任务一致。
(4)可以用于实现任务间的互斥访问
获取信号量/试图信号量-1:BaseType_t xSemaphoreTake(SemaphoreHandle_t xSemaphore, TickType_t xTicksToWait);
(信号量的P操作)创建互斥信号量
QueueHandle_t xSemaphoreCreateMutex( void );
返回值:互斥量句柄(队列,因为信号量的底层实现是通过队列完成的);
若返回NULL,则创建失败
申请占用一个互斥量/申请获取访问公共资源的令牌/申请占用一个公共资源/试图让信号量-1/P操作 BaseType_t xSemaphoreTake ( QueueHandle_t xQueue, TickType_t xTicksToWait )
参数:xQueue 信号量句柄
xTicksToWait 超时时间,单位:节拍
返回值:若成功占用,返回pdPASS
若未能成功占用,返回errQUEUE_EMPTY
互斥量中很多数据和队列有关,原因是互斥量底层是基于深度为1的队列实现的!
释放一个互斥量/归还访问公共资源的令牌/释放一个占用的公共资源/使信号量+1/V操作
BaseType_t xSemaphoreGive( QueueHandle_t xQueue )
参数:xQueue 信号量句柄
返回值:若成功释放,返回pdPASS
若释放前,互斥量已存在(值为1),则返回errQUEUE_FULL
5)事件组:
在 FreeRTOS 中,事件组(Event Group)是一个用于管理和同步任务的机制。它允许任务之间通过事件标志(bits)来通信和同步。事件组中的每一位(bit)代表一个独立的事件,任务可以设置、清除、等待或查询这些事件标志位。
(1)事件组的主要功能:
设置事件标志位:任务或中断服务例程可以设置一个或多个事件标志位,以表示某些事件已经发生。
清除事件标志位:任务可以清除一个或多个事件标志位,以重置或表示某些事件已经处理完毕。
等待事件标志位:任务可以阻塞等待,直到一个或多个特定的事件标志位被设置。这种等待可以是一直等待,直到所有指定的事件都发生,或者只要其中的一个事件发生就退出等待。
查询事件标志位:任务可以查询当前事件组的状态,以检查哪些事件已经发生。
1.创建事件组
| 原型:EventGroupHandle_t xEventGroupCreate( void ); |
| 功能:创建一个事件组,并返回它的句柄 |
| 参数:无 |
| 返回值:返回事件组的句柄。如果返回 NULL,表示事件组创建失败。 |
2.设置事件标志位
| 原型:EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ); |
| 功能:设置事件组中的一个或多个事件标志位,即触发事件。 |
| 参数:xEventGroup:事件组句柄。 uxBitsToSet:要设置的事件标志位。 |
| 返回值:返回设置前事件组的事件标志位。 |
| 备注:每种事件标志位具体对应第几位,以及该标志位的含义,都是由开发者自行规定。 |
3.清除事件标志位
| 原型:EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ); |
| 功能:清除事件组中的一个或多个事件标志位。 |
| 参数:xEventGroup:事件组句柄。 uxBitsToClear:要清除的事件标志位。 |
| 返回值:返回清除前事件组的事件标志位。 |
4.等待事件标志位☆
| 原型:EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToWaitFor, const BaseType_t xClearOnExit, const BaseType_t xWaitForAllBits, TickType_t xTicksToWait ); |
| 功能:等待一个或多个事件标志位被设置。 |
| 参数:xEventGroup:事件组句柄。 uxBitsToWaitFor:等待的事件标志位。如果等待多种事件,就用按位或 | 连接 xClearOnExit:退出时是否清除事件标志位,pdTRUE 表示清除,pdFALSE 表示不清除。 xWaitForAllBits:等待所有指定的事件标志位都被设置,pdTRUE 表示等待所有, pdFALSE 表示任意一个。 xTicksToWait:等待的最大时间(以时钟节拍计),如果设置为 portMAX_DELAY,表示无限等待。 |
| 返回值:返回清零前的事件组的值。 |
openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐


所有评论(0)