【学习FreeRTOS】第17章——FreeRTOS任务通知

stm32——freeRTOS任务通知 freeRTOS从版本v8.2.0开始提供任务通知这个功能,每个任务都有一个32位的通知值。按照freeRTOS官方说法,使用消息通知比通过二进制信号量方式解除阻塞快45%,并且更加省内存(无需创建队列)。在大多数情况下,任务通知可以替代二值信号量、计数信号量、事件标志组,可以替代长度为1的队列(可以保持一个32位整数或指针值),并且任务通知速度更快,使用RAM更少。 阅读详情

1.任务通知的简介

任务通知:用来通知任务的,任务控制块中的结构体成员变量 ulNotifiedValue就是这个通知值。

  • 使用队列、信号量、事件标志组时都需另外创建一个结构体,通过中间的结构体进行间接通信!
    在这里插入图片描述
  • 使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发过来的"通知"
    在这里插入图片描述

任务通知值的更新方式

  • 不覆盖接受任务的通知值【类似队列不覆写】
  • 覆盖接受任务的通知值【类似队列覆写】
  • 更新接受任务通知值的一个或多个bit【类似任务标志组】
  • 增加接受任务的通知值【类似信号量】
  • 只要合理,灵活的利用任务通知的特点,可以在一些场合中替代队列、信号量、事件标志组!

任务通知的优势及劣势

  • 效率更高(快):使用任务通知向任务发送事件或数据比使用队列、事件标志组或信号量快得多
  • 使用内存更小:使用其他方法时都要先创建对应的结构体,使用任务通知时无需额外创建结构体

  • 无法发送数据给ISR:ISR没有任务结构体,所以无法给ISR发送数据。但是ISR可以使用任务通知的功能,发数据给任务
  • 无法广播给多个任务:任务通知只能是被指定的一个任务接收并处理
  • 无法缓存多个数据:任务通知是通过更新任务通知值来发送数据的,任务结构体中只有一个任务通知值,只能保持一个数据
  • 发送受阻不支持阻塞:发送方无法进入阻塞状态等待

任务通知有速度快、内存小的优势,但是中断不能收数据,只能一对一,只有一个数据量,发送不支持阻塞。多用于一对一通知

2.任务通知值和通知状态

任务都有一个结构体:任务控制块TCB,它里边有两个结构体成员变量:

typedef  struct  tskTaskControlBlock 
{
	//… …
    #if ( configUSE_TASK_NOTIFICATIONS  ==  1 )
    	volatile  uint32_t	ulNotifiedValue [ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
        volatile  uint8_t  	ucNotifyState 	[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
    endif
	//… …
} tskTCB;
#define  configTASK_NOTIFICATION_ARRAY_ENTRIES	1  	/* 定义任务通知数组的大小, 默认: 1 */

ulNotifiedValue是 uint32_t 类型,用来表示通知值
ucNotifyState是 uint8_t 类型,用来表示通知状态

任务通知值的更新方式有多种类型

  • 计数值(数值累加,类似信号量)
  • 相应位置一(类似事件标志组)
  • 任意数值(支持覆写和不覆写,类似队列)

任务通知状态共有3种取值:

#define	taskNOT_WAITING_NOTIFICATION  	( ( uint8_t ) 0 )		 /* 任务未等待通知 */
#define taskWAITING_NOTIFICATION		( ( uint8_t ) 1 )		 /* 任务在等待通知 */
#define taskNOTIFICATION_RECEIVED       ( ( uint8_t ) 2 )		 /* 任务在等待接收 */
  • 任务未等待通知 :任务通知默认的初始化状态
  • 等待通知:接收方已经准备好了(调用了接收任务通知函数),等待发送方给个通知
  • 等待接收:发送方已经发送出去(调用了发送任务通知函数),等待接收方接收

3.任务通知相关API函数介绍

任务通知API函数主要有两类:①发送通知 ,②接收通知。
【注意】发送通知API函数可以用于任务和中断服务函数中;接收通知API函数只能用在任务中。

  • xTaskNotify():发送任务通知,带有通知值
  • xTaskNotifyAndQuery():发送任务通知,带有通知值,保留接收任务原通知值
  • xTaskNotifyGive():发送任务通知,不带通知值
  • xTaskNotifyFromISR():在中断中发送任务通知
  • xTaskNotifyAndQueryFromISR():在中断中发送任务通知
  • vTaskNotifyGiveFromISR():在中断中发送任务通知
  • ulTaskNotifyTake():获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减一。
  • xTaskNotifyWait():获取任务通知,比 ulTaskNotifyTak()更为复杂,可获取通知值和清除通知值的指定位。

xTaskNotifyAndQuery()和xTaskNotify()常用于模拟写队列/设置标志位,ulTaskNotifyTake()常用于读队列/清除标志位
xTaskNotifyGive()常用于模拟信号量释放,ulTaskNotifyTake()常用于模拟信号量获取
下方的函数和上述的函数基本一致,只不过可以操作下表不为0的元素操作(不常用)
在这里插入图片描述

3.1.发送任务通知

#define	xTaskNotifyAndQuery(xTaskToNotify,  ulValue ,  eAction ,  pulPreviousNotifyValue  )
		xTaskGenericNotify((xTaskToNotify), (tskDEFAULT_INDEX_TO_NOTIFY), (ulValue), (eAction),	(pulPreviousNotifyValue ))
#define	xTaskNotify(xTaskToNotify ,  ulValue ,  eAction  )
 		xTaskGenericNotify((xTaskToNotify), (tskDEFAULT_INDEX_TO_NOTIFY), (ulValue), (eAction),  NULL)
#define	xTaskNotifyGive(  xTaskToNotify  )
		xTaskGenericNotify((xTaskToNotify), (tskDEFAULT_INDEX_TO_NOTIFY),  (0), 	  eIncrement, NULL)

BaseType_t xTaskGenericNotify(	TaskHandle_t 	xTaskToNotify,
                                UBaseType_t 	uxIndexToNotify,
                                uint32_t 		ulValue,
                                eNotifyAction 	eAction,
                                uint32_t * 		pulPreviousNotificationValue  )
                                
typedef  enum
{    
	eNoAction = 0, 				/* 无操作 */
	eSetBits					/* 更新指定bit */
	eIncrement					/* 通知值加一 */
 	eSetValueWithOverwrite		/* 覆写的方式更新通知值 */
	eSetValueWithoutOverwrite	/* 不覆写通知值 */
} eNotifyAction;
  • 形参xTaskIaNatify:接收任务通知的任务句柄
  • 形参uxIndexToNotify:任务的指定通知(任务通知相关数组成员,第0个元素)
  • 形参ulValue:任务通知值
  • 形参eAction:通知方式(通知值更新方式)
  • 形参pulPreviousNotificationValue:用于保存更新前的任务通知值(为NULL则不保存)

3.2.发送任务通知底层函数xTaskGenericNotify( )解析

在这里插入图片描述

3.3.获取任务通知

#define ulTaskNotifyTake( xClearCountOnExit  ,   xTicksToWait )
		ulTaskGenericNotifyTake	( ( tskDEFAULT_INDEX_TO_NOTIFY ),//任务的指定通知
								( xClearCountOnExit ),
								( xTicksToWait ) ) 
  • 形参uxlndexToWaitQn:任务的指定通知(任务通知相关数组成员)
  • 形参xClearCountOnExit:指定在成功接收通知后,将通知值清零或减1,pdTRUE:把通知值清零;pdEAL.SE:把通知值减一
  • 形参xTicksToWait:阻塞等待任务通知值的最大时间
  • 返回值:0,接收失败;非0,接收成功,返回任务通知的通知值
#define xTaskNotifyWait( 			ulBitsToClearOnEntry,
									ulBitsToClearOnExit, 
									pulNotificationValue, 
									xTicksToWait)
		xTaskGenericNotifyWait( 	tskDEFAULT_INDEX_TO_NOTIFY,
									( ulBitsToClearOnEntry ),
									( ulBitsToClearOnExit ), 
									( pulNotificationValue ),
									( xTicksToWait )) 

BaseType_t xTaskGenericNotifyWait( 	UBaseType_t 	uxIndexToWaitOn,
									uint32_t 		ulBitsToClearOnEntry,
									uint32_t 		ulBitsToClearOnExit,
									uint32_t * 		pulNotificationValue,
									TickType_t 		xTicksToWait);
  • 形参uxlndexToWaitOn:任务的指定通知(任务通知相关数组成员)
  • 形参ulBitesToClearOnEntry:等待前清零指定任务通知值的比特位(旧值对应bit清0)
  • 形参ulBitesToClearOnExit:成功等待后清零指定的任务通知值比特位(新值对应bit清0)
  • 形参pulNotificationValue:用来取出通知值(如果不需要取出,可设为NULL)
  • 形参xTicksToWait:阻塞等待任务通知值的最大时间
  • 返回值:pdTRUE,等待任务通知成功;pdFALSE,等待任务通知失败

3.4.ulTaskNotifyTake( )与xTaskNotifyWait( )函数解析

  • ulTaskNotifyTake( )
    在这里插入图片描述
  • ulTaskNotifyTake( )
    在这里插入图片描述

4.任务通知模拟信号量实验

  • 实验目的:学习使用 FreeRTOS 中的任务通知功能模拟二值信号量和计数型信号量
  • 实验设计:将设计三个任务:start_task、task1、task2
    start_task用来创建task1和task2任务
    task1用于按键扫描,当检测到按键KEY0被按下时,将发送任务通知
    task2用于接收任务通知,并打印相关提示信息
    在这里插入图片描述

5.任务通知模拟消息邮箱实验

  • 实验目的:学习使用 FreeRTOS 中的任务通知功能模拟消息邮箱
  • 实验设计:将设计三个任务:start_task、task1、task2
    start_task用来创建task1和task2任务
    task1用于按键扫描,将按下的按键键值通过任务通知发送给指定任务
    task2用于接收任务通知,并根据接收到的数据做相应动作

在这里插入图片描述

6.任务通知模拟事件标志组实验

  • 实验目的:学习使用 FreeRTOS 中的任务通知功能模拟事件标志组
  • 实验设计:将设计三个任务:start_task、task1、task2
    start_task用来创建task1和task2任务
    task1用于按键扫描,当检测到按键按下时,发送任务通知设置不同标志位
    task2用于接收任务通知,并打印相关提示信息

在这里插入图片描述

5.5 RTOS任务通知(Task Notification) FreeRTOS任务通知是一种高效的任务间通信机制,通过将通信通道内嵌到任务控制块(TCB)中,实现直接的事件和数据传递。每个任务拥有32位通知值和通知状态字段,支持四种发送模式(设置、覆盖、递增、位操作)和两种接收方式(信号量模拟和通用等待)。相比传统通信方式,任务通知无需创建内核对象,执行速度更快(比信号量快45%),内存开销为零,适用于二进制/计数信号量、事件标志和轻量级消息邮箱等场景。其核心优势在于极致的轻量化和确定性操作,特别适合对性能敏感的嵌入式应用。 阅读详情

相关推荐

【嵌入式——FreeRTOS】任务通知

嵌入式-FreeRTOS-任务通知

weixin_39723539的博客 1611

FreeRTOS-任务通知详解

本文的重点主要有两点:1.搞明白任务通知的三个状态(实现任务通知的关键),2.明白任务通知的优缺点,以及任务通知模拟出来的队列、信号量、事件组与真实的有何区别。

k666499436的博客 6189

FreeRTOS --(17)任务通知浅析

之前聊到,FreeRTOS 可以通过信号量(二值信号量和计数信号量)、队列、事件组来同步任务与任务,任务与中断; 在 FreeRTOS 中,还有一个东西也可以用作任务与任务,中断与任务的同步,它叫任务通知(Task Notifications); 如果我们通过信号量、队列、事件组的形式来同步,在 FreeRTOS 中,叫通过了一个Communication Object;也就是说通过了一个用于连续接收方和发送方的中间模块; FreeRTOS 的任务通知(Task Notifications),..

StephenZhou 7693

FreeRTOS入门(06):任务通知

任务通知(TaskNotify)是RTOS中相对常用的用于任务间交互的功能,这篇文章将对相关内容做个介绍。

Naisu的各种笔记 2231

FreeRTOS任务通知

——————(正点原子FreeRTOS学习笔记) 开始学习FreeRTOS,学习参考书籍和视频来自正点原子FreeRTOS源码详解与应用开发,北京航空航天大学出版社 1    任务通知简介         任务通知在 FreeRTOS 中是一个可选的功能,要使用任务通知的话就需要将宏configUSE_TASK_NOTIFICATIONS 定义为 1。FreeRTOS 的每个任务

nippon1218的博客 5889

17.FreeRTOS直接任务通知 Notification

FreeRTOS 直接任务通知提供了一种高效的任务间通信机制,可以实现任务间的同步和协作,适用于多种实时嵌入式系统中。通过简单的 API 调用,任务可以发送和接收直接任务通知,从而实现灵活的任务管理和事件触发。

宁子希的博客 1362

17-FreeRTOS任务通知

答:任务通知API函数主要有两类:1-发送通知,2-接收通知。注意:发送通知API函数可以用于任务和中断函数中,但接受通知API函数只能用在任务中。

qq_37391577的博客 815

FreeRTOS中任务栈内存分配

前言 在RAM中大多数的空间分配为任务栈和系统栈两部分。 任务栈:顾名思义就是用来跑任务的,当我们xTaskCreate一个任务时,但是在这块任务栈里面动态分配空间。 系统栈:任务栈是不使用这里的空间的,用到这里一般都是中断函数和中断嵌套。 大多数在移植了freertos后,没怎么用RAM,但是发现RAM内存都快没了,那是freertos中有个动态分配的任务栈空间大小的宏,configTOTAL_HEAP_SIZE,老版本的freertos中没有静态创建任务,是用动态分配一块RAM空间给任务栈。

weixin_47321452的博客 1万+

FreeRTOS笔记——17任务通知

任务通知方式eNoAction = 0, /* 无操作 */eSetBits /* 更新指定bit 类似事件标志组*/eIncrement /* 通知值加一 类似计数型信号量*/eSetValueWithOverwrite /* 覆写的方式更新通知值 类似给队列发送消息*/eSetValueWithoutOverwrite /* 不覆写通知值 */任务通知状态。

m0_74375685的博客 1114

FreeRTOS任务间通信

消息队列:不同任务或进程之间传递消息互斥锁:侧重于保证同一时刻只有一个线程可以访问共享资源信号量:控制对共享资源访问的同步机制,用于控制多个线程对共享资源的访问数量。事件组:管理多个事件的同步机制,允许多个任务等待多个事件的发生任务通知:任务之间直接发送通知,任务间通信线程间同步:信号量,互斥锁,事件组线程间通信:消息队列,任务通知。

m0_61973119的博客 2774

FreeRTOS任务切换

将当前运行的任务的寄存器保存到栈中,再将就绪任务的数据从栈中保存到寄存器,然后运行。

Calmer_的博客 1996

freeRTOS任务通知(1-17)

def: 任务通知是用来通知任务的,任务控制块中的结构体成员变量ulNotifiedValue就是这个通知值。任务通知的内存消耗比较小1: 使用队列,信号量,时间标志组都需要另外创建结构体,通过中间结构体进行间接通信。2:使用任务通知时,任务结构体TCB中就包含了内部对象,可以直接接收别人发送过来的通知。任务通知值的更新方式1:不覆盖接收任务通知值2:覆盖接收任务的通知值3:更新接受任务通知值的一个或多个bit4:增加接受任务的通知值。

qq_45973003的博客 1083

ESP32学习笔记(2)FreeRTOS上手使用指南

ESP32学习笔记(2)FreeRTOS上手使用指南 文章目录ESP32学习笔记(2)FreeRTOS上手使用指南FreeRTOS的可配置参数配置参数demo可配置的参数简要说明FreeRTOS 使用指南(API)一个最简单的使用demo写两个任务在main中创建任务执行一、 变量类型定义二、 任务函数2.1 任务创建2.2 任务删除2.3 任务延时2.4 任务延迟到指定时间2.5 获得任务优先级2.6 设置任务优先级2.7 挂起任务2.8 唤醒挂起的任务2.9 从中断唤醒挂起的任务2.10 为任务分配标签

兰陵笑笑生SD的博客 7295

FreeRTOS --(17)任务通知实战:从信号量替代到高效同步

本文深入探讨了FreeRTOS任务通知的高效应用,重点解析了如何利用xTaskNotifyGive、ulTaskNotifyTake等API替代传统信号量,实现任务间同步。通过对比二值/计数信号量、事件组及邮箱的替代方案,揭示了任务通知在内存开销和运行速度上的显著优势,为资源受限的嵌入式系统提供了轻量级同步通信的实战指南。

yog99的博客 953

17.任务通知

任务通知

扬帆起航 1061

RAGFlow API 实战指南:从数据集管理到智能对话

本文提供了RAGFlow API的实战指南,详细介绍了如何从零开始构建基于检索增强生成(RAG)的智能应用。内容涵盖环境准备、API密钥获取、核心概念理解,以及通过API进行数据集创建与管理、文档上传解析、知识块管理、检索测试,最终创建并配置智能聊天助手,实现基于私有知识库的精准对话。

weixin_29284885的博客 379

freeRTOS学习

FreeRTOS快速入门----2023/12/25重启韦东山老师RTO。笔记

LDBH66的博客 6239

Orin 调试GMSL camera 96712手册重点

96712基础理解

乐于分享 9186

FreeRTOS(任务通知&软件定时&低功耗&内存管理)

任务通知是 FreeRTOS 中一种用于任务间通信的机制,它允许一个任务向其他任务发送简单的通知或信号,以实现任务间的同步和协作。任务通知通常用于替代二值信号量或事件标志组,提供了更轻量级的任务间通信方式。大多数任务间通信方法通过中间对象,如队列、信号量或事件组。发送任务写入通信对象,接收任务从通信对象读取。当使用直接任务通知时,顾名思义,发送任务直接向接收任务发送通知,而无需中间对象。

jzxnb521的博客 1162

RK3588 hdmiout调试(一)

RK3588 hdmiout调试(一)

目前从事linux驱动开发,多交流多学习吧 5169

LED灯闪烁实验:实验介绍

每个章节都会单独进行验证工作,例如Simulink开发的应用层软件,会在Simulink-TestHarness中进行仿真,通过Scope示波器模块输出0-1交替的结果。CubeIDE集成双方的代码后,会烧写到开发板中验证是否按照定义的时间进行闪烁。ST-LINK V2是STM32开发生态系统中常用的硬件调试接口,能够连接微控制器与开发环境,实现程序的下载、调试和分析。STM32F103C8T6最小系统板是基于STM32F103C8T6微控制器的开发板,本实验会涉及使用板载的连接PC13引脚的LED灯。

u013288925的博客 456
上一篇: 【学习FreeRTOS】第16章——FreeRTOS事件标志组
下一篇: 【学习FreeRTOS】第18章——FreeRTOS软件定时器
Sunny_Coder
博客等级 码龄7年 124粉丝 69原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值