FreeRTOS(任务通知)

资料来源于硬件家园:资料汇总 - FreeRTOS实时操作系统课程(多任务管理)

目录

一、任务通知的概念

1、概念

2、发送通知给任务的方式

3、任务通知使用限制

二、任务通知的运行机制

三、任务通知的API函数

1、任务通知的数据结构

2、常用的API函数

3、函数xTaskNotifyGive()

4、函数ulTaskNotifyTake()

5、函数xTaskNotify()

6、函数ulTaskNotifyWait()

7、使用说明

四、任务通知代替二值信号量

五、任务通知代替计数信号量

六、任务通知代替队列

七、任务通知代替事件组


一、任务通知的概念

1、概念

FreeRTOS 从 V8.2.0 版本开始提供任务通知功能,每个任务都有一个 32位的通知值,在多数情况下,任务通可以替代二值信号量、计数信号量、事件组,也可以替代长度为1的队列(可以保存一个 32位整数或指针值)。

相对于以前使用 FreeRTOS 内核通信的资源时必须创建队列、二进制信号量、计数信号量或事件组的情况,使用任务通知显然更灵活。按照 FreeRTOS 官方的说法,使用任务通知比通过信号量等ICP通信方式解除阻塞的任务速度快45%,并且更加省RAM内存空间,任务通知的使用无须创建队列。要想使用任务通知,必须将FreeRTOSConfig.h中的宏定义configUSE_TASK_NOTIFICATIONS设置为1。其实 FreeRTOS 默认是为1的,所以任务通知是默认可用的。

2、发送通知给任务的方式

> 发送通知给任务,如果有通知未读,则不覆盖通知值。

> 发送通知给任务,直接覆盖通知值。

>发送通知给任务, 设置通知值的一个或者多个位,可以当作事件组来使用。

> 发送通知给任务,递增通知值,可以当作信号量使用。

通过对以上任务通知方式的合理使用,可以在一定场合下替代 FreeRTOS 的信号量、队列、事件组等。

3、任务通知使用限制

当然,凡事都有利弊,消息通知虽然处理更快,RAM 开销更小,但也有以下限制:

>只能有一个任务接收通知消息,因为必须指定接收通知的任务。

>只有等待通知的任务可以被阻塞,发送通知的任务在任何情况下都不会因为发送失败

而进入阻塞态。

二、任务通知的运行机制

任务通知属于任务附带的资源,所以在任务被创建时,任务通知也被初始化,我们知道在使用队列、信号量前,必须先创建队列和信号量,目的是创建队列数据结构,比如使用xQueueCreate() 函数创建队列,用xSemaphoreCreateBinary()函数创建二值信号量等。再来看任务通知,由于任务通知的数据结构包含在任务控制块中,只要任务存在,任务通知数据结构就已经创建完毕,可以直接使用,所以使用时很方便

任务通知可以在任务中向指定任务发送通知,也可以在中断中向指定任务发送通知。FreeRTOS的每个任务都有一个32位的通知值,任务控制块中的成员变量ulNotifiedValue 就是这个通知值。只有在任务中可以等待通知,而不允许在中断中等待通知。如果任务在等待的通知暂时无效,任务会根据用户指定的阻塞超时时间进入阻塞状态,我们可以将等待通知的任务看作消费者;其他任务和中断可以向等待通知的任务发送通知,发送通知的任务和中断服务函数可以看作生产者,当其他任务或者中断向这个任务发送任务通知,且任务获得通知以后,该任务就会从阻塞态中解除,这与 FreeRTOS 中内核的其他通信机制一致。

三、任务通知的API函数

1、任务通知的数据结构

任务通知是任务控制块的资源,属于任务控制块中的成员变量。

ulNotifiedValue: 任务通知值,用于保存一个32位整数或指针值

ucNotifyState:  任务通知状态,用于标识任务的通知状态

2、常用的API函数

① 替代二值信号量与计数信号量

发送任务通知:

xTaskNotifyGive()

vTaskNotifyGiveFromISR()

获取任务通知:

ulTaskNotifyTake()

② 替代长为1的队列与事件组

发送任务通知:

xTaskNotify()

vTaskNotifyFromISR()

获取任务通知:

ulTaskNotifyWait()

3、函数xTaskNotifyGive()

① 函数原型

 功能如下:在任务中向指定任务发送通知,使任务通知值加1,这种方式用于信号量

②形参说明

形参1:任务句柄

形参2: 任务通知值,取0

形参3: 指示任务控制块中的变量 ulNotifiedValue 实现加一操作

形参4:空

③返回值

没有超时机制,永远返回pdPASS

4、函数ulTaskNotifyTake()

① 函数原型

功能如下:在任务中获取通知,与xTaskNotifyGive()配套使用,用于替代二值信号量与计数信号量

②形参说明

形参1:退出时是否清零计数。pdTRUE->清零, pdFALSE -> 减1

形参2: 超时时间,单位为系统节拍

③返回值

返回任务之前的任务通知值

5、函数xTaskNotify()

① 函数原型

功能如下:在任务中向指定任务发送通知,根据eAction的值完成不同操作

②形参说明

形参1:任务句柄

形参2: 任务通知值

形参3: 如下图片

形参4: 空

③返回值

根据上面第 3 个形参的说明,将其设置为 eSetValueWithoutOverwrite,有可能返回pdFALSE,其余所有情况都返回值 pdPASS

6、函数ulTaskNotifyWait()

① 函数原型

功能如下:在任务中获取通知,与xTaskNotify()配套使用,用于替代长度位1的队列与事件组

②形参说明

形参1:进入函数时,清除哪些位  ->  0:无变化    1:清除相应位

形参2:退出函数时,清除哪些位  ->  0:无变化    1:清除相应位

形参3:保存通知值

形参4: 超时时间,单位为系统节拍

③返回值

pdTRUE: 获取任务通知成功

pdFALSE:获取任务通知失败

7、使用说明

四、任务通知代替二值信号量

五、任务通知代替计数信号量

 

 

六、任务通知代替队列

 

 

七、任务通知代替事件组

 

 

### 关于 FreeRTOS 任务通知机制 #### 实现方式 FreeRTOS 提供了一种轻量级的通知机制来替代信号量或事件标志组,允许一个任务、中断服务程序 (ISR) 或另一个任务向目标任务发送通知。这种机制通过修改目标任务中的成员变量 `ulNotifiedValue` 来工作[^3]。 当使用任务通知时,不需要创建额外的对象如队列或信号量,从而减少了内存占用并提高了效率。每个任务都有自己的通知(`ulNotifiedValue`) 和状态位图用于处理多个并发通知源的情况。 #### 使用场景 - **唤醒休眠的任务**:可以用来代替二进制或计数型互斥锁。 - **传递数据给任务**:可以直接设置数值到被通知任务中去。 - **从 ISR 中高效地通知任务**:相比其他同步原语更加适合在中断上下文中调用因为其原子性和低延迟特性。 #### API 函数介绍 为了操作任务通知FreeRTOS 提供了一系列API接口: - `void vTaskNotifyGive( TaskHandle_t xTaskToNotify );` - 增加指定任务通知计数器一次,并可能将其解除阻塞状态。 - `BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );` - 阻塞等待直到接收到至少一条消息为止;可以选择清除某些特定的状态位以及获取当前的通知值。 - `BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );` - 清除某个任务通知状态(即将该任务置为未通知),这不会影响实际存储的数据(`ulNotifiedValue`)本身。 - `uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );` - 获取并返回任务通知值,在退出前可选择是否清零已读取的数量。 ```c // 示例代码展示如何在一个简单的应用程序里利用任务间通信功能 #include "FreeRTOS.h" #include "task.h" #define STACK_SIZE configMINIMAL_STACK_SIZE static void prvSenderTask(void* pvParameters){ while(true){ // 发送通知给接收者任务 vTaskNotifyGive((TaskHandle_t)pvParameters); // 模拟一些工作负载 vTaskDelay(pdMS_TO_TICKS(100)); } } static void prvReceiverTask(){ uint32_t received_value; for (;;){ // 等待来自发送者的通知 if(xTaskNotifyWait(0, ULONG_MAX, &received_value, portMAX_DELAY)){ printf("Received notification with value %lu\n", received_value); // 处理接收到的信息... } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zhang丶&|!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值