FreeRTOS 快速入门(八)之任务通知


一、任务通知

1、基本概念

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

相对于以前使用 FreeRTOS 内核通信的资源,必须创建队列、二进制信号量、计数信号量或事件组的情况,使用任务通知显然更灵活。按照 FreeRTOS 官方的说法,使用任务通知比通过信号量等 ICP 通信方式解除阻塞的任务要快 45%,并且更加省 RAM 内存空间(使用 GCC 编译器,-o2 优化级别),任务通知的使用无需创建队列。

想要使用任务通知,必须将 FreeRTOSConfig.h 中的宏定义 configUSE_TASK_NOTIFICATIONS 设置为 1,其实FreeRTOS 默认是为 1 的,所以任务通知是默认使能的。

FreeRTOS 提供以下几种方式发送通知给任务 :

  • 发送通知给任务, 如果有通知未读,不覆盖通知值。
  • 发送通知给任务,直接覆盖通知值。
  • 发送通知给任务,设置通知值的一个或者多个位 ,可以当做事件组来使用。
  • 发送通知给任务,递增通知值,可以当做计数信号量使用。

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

2、优势及限制

任务通知的优势:

  • 效率更高:使用任务通知来发送事件、数据给某个任务时,效率更高。比队列、信号量、事件组都有大的优势。
  • 更节省内存:使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体。

任务通知的限制:

  • 不能发送数据给 ISR:ISR 并没有任务结构体,所以无法使用任务通知的功能给 ISR 发送数据。但是 ISR 可以使用任务通知的功能,发数据给任务。
  • 数据只能给该任务独享
  • 无法缓冲数据
  • 无法广播给多个任务
  • 如果发送受阻,发送方无法进入阻塞状态等待

3、通知状态和通知值

每个任务都有一个结构体:TCB(Task Control Block),里面有 2 个成员:

  • 一个是 uint8_t 类型,用来表示通知状态
  • 一个是 uint32_t 类型,用来表示通知值
typedef struct tskTaskControlBlock
{
   
   
	......
	/* configTASK_NOTIFICATION_ARRAY_ENTRIES = 1 */
	volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
	volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
	......
} tskTCB;

通知状态有 3 种取值:

  • taskNOT_WAITING_NOTIFICATION:任务没有在等待通知
  • taskWAITING_NOTIFICATION:任务在等待通知
  • taskNOTIFICATION_RECEIVED:任务接收到了通知,也被称为 pending(有数
### FreeRTOS 快速入门教程第五部分内容 FreeRTOS是一款广泛应用于嵌入式系统的实时操作系统,其快速入门教程通常会分为多个部分逐步介绍核心概念和功能模块。根据已有的资料[^1],可以推测第五部分内容可能涉及更深层次的任务管理、调度器配置以及任务间的通信机制。 #### 任务间通信与同步 在FreeRTOS中,任务间通信是一个重要主题,主要包括三种主要方式:任务通知、队列和信号量[^3]。这些机制各有特点,在实际应用中可以根据需求选择合适的工具: - **任务通知**:一种轻量级的通信方法,适合简单的状态传递或事件触发场景。 - **队列**:支持数据传输的功能,适用于需要在任务之间交换复杂消息的情况。 - **信号量**:主要用于资源锁定或任务同步,包括二值信号量和计数信号量两种形式。 这部分内容可能会详细介绍如何使用上述机制实现高效的多任务协作,并通过实例演示具体操作流程。 #### 实践案例分析 为了加深理解,许多教程会在这一阶段提供实践案例来展示FreeRTOS的实际应用场景[^2]。例如,“深入理解FreeROS队列之队列实战”章节就属于此类进阶内容之一,它不仅讲解理论知识还配有动手实验环节指导学员完成特定目标。 以下是创建并初始化一个简单队列的例子: ```c #include "FreeRTOS.h" #include "queue.h" // 定义队列句柄 QueueHandle_t xQueue; void vAFunction( void ) { const TickType_t xTicksToWait = pdMS_TO_TICKS( 100 ); // 创建具有十个整型空间大小的队列 xQueue = xQueueCreate( 10, sizeof( int ) ); if( xQueue != NULL ){ int xValueToSend = 99; // 向队列发送数值 if( xQueueSend( xQueue , &xValueToSend , xTicksToWait ) == pdPASS ){ // 发送成功后的处理逻辑... } }else{ // 队列创建失败错误提示... } } ``` 此代码片段展示了如何定义、创建以及向队列发送数据的过程。
评论 18
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值