freeRTOS--任务通知

一、什么是任务通知

使用任务通知可以替换二值信号量、计数信号量、事件标志组,可以替代长度为1的队列,任务通知速度更快、使用的RAM更少。

任务通知值的更新方式:

  1. 发消息给任务,如果有通知未读,不覆盖通知值。
  2. 发消息给任务,直接覆盖通知值。
  3. 发消息给任务,设置通知值的一个或多个 位
  4. 发送消息给任务,递增通知值

任务通知的相关API函数:

1.发送通知

1.发送通知
函数描述
xTaskNotify()
发送通知,带有通知值
xTaskNotifyAndQuery()
发送通知,带有通知值并且保留接收任务的原通知值
xTaskNotifyGive()

发送通知,不带通知值

xTaskNotifyFromISR()
在中断中发送任务通知
vTaskNotifyGiveFromISR()
在中断中发送任务通知

BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify,
uint32_t ulValue,
eNotifyAction eAction );

 

xTaskToNotify:需要接收通知的任务句柄;
ulValue:用于更新接收任务通知值, 具体如何更新由形参 eAction 决定;
eAction:一个枚举,代表如何使用任务通知的值;

枚举
枚举值描述
eNoAction
发送通知,但不更新值(参数 ulValue 未使用)
eSetBits
被通知任务的通知值按位或 ulValue 。(某些场景下可代替事件组,效率更高)

 

eSetValueWithOverWrite
被通知任务的通知值设置为 ulValue 。(某些场景下可代替 xQueueOverwrite ,效率更高)
eSetValueWithoutOverwrite
如果被通知的任务当前没有通知,则被通知的任务的通知值 设为ulValue
如果被通知任务没有取走上一个通知,又接收到了一个通 知,则这次通知值丢弃,在这种情况下视为调用失败并返回 pdFALSE (某些场景下可代替 xQueueSend ,效率更高)

返回值:如果被通知任务还没取走上一个通知,又接收了一个通知,则这次通知值未能更新并返回
pdFALSE, 而其他情况均返回pdPASS。

BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t *pulPreviousNotifyValue );
参数:
xTaskToNotify:需要接收通知的任务句柄; 
ulValue:用于更新接收任务通知值, 具体如何更新由形参 eAction 决定; 
eAction:一个枚举,代表如何使用任务通知的值;
pulPreviousNotifyValue:对象任务的上一个任务通知值,如果为 NULL, 则不需要回传, 这个时
候就等价于函数 xTaskNotify()。

返回值:
如果被通知任务还没取走上一个通知,又接收了一个通知,则这次通知值未能更新并返回pdFALSE, 而其他情况均返回pdPASS。
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );

//参数:xTaskToNotify:接收通知的任务句柄, 并让其自身的任务通知值加 1。
//返回值:总是返回pdPASS。

2.等待通知

等待通知 API 函数只能用在任务,不可应用于中断中!

等待通知

函数描述
ulTaskNotifyTake()
获取任务通知,可以设置在退出此函数的时候将任务通知值清零或者减 一。当任务通知用作二值信号量或者计数信号量的时候,使用此函数来 获取信号量。
xTaskNotifyWait()
获取任务通知,比  ulTaskNotifyTak() 更为复杂,可获取通知值和清除通 知值的指定位

 

uint32_t ulTaskNotifyTake ( BaseType_t xClearCountOnExit , TickType_t xTicksToWait );

参数:xClearCountOnExit:指定在成功接收通知后,将通知值清零或减 1pdTRUE:把通知值清零(二 值信号量);pdFALSE:把通知值减一(计数型信号量); xTicksToWait:阻塞等待任务通知值 的最大时间;

返回值:0:接收失败 非0:接收成功,返回任务通知的通知值

BaseType_t xTaskNotifyWait ( uint32_t ulBitsToClearOnEntry ,
uint32_t ulBitsToClearOnExit ,
uint32_t * pulNotificationValue ,
TickType_t xTicksToWait );
ulBitsToClearOnEntry :函数执行前清零任务通知值那些位 。
ulBitsToClearOnExit :表示在函数退出前,清零任务通知值那些位,在清 0 前,接收到的任务通知值会先被保存到形参 *pulNotificationValue 中。
pulNotificationValue :用于保存接收到的任务通知值。 如果 不需要使 用,则设置为 NULL 即可 。
xTicksToWait :等待消息通知的最大等待时间。

 二、实验

1.模拟二值信号量和计数型信号量

void StartTaskSend(void const * argument)
{
  
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
			{
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET)
			{
				xTaskNotifyGive(TaskReceiveHandle);
				//printf("任务通知:模拟二值信号量发送成功 !\r\n");
				printf("任务通知:模拟计数型信号量发送成功 !\r\n");
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0) == RESET);
			}
				
				
    osDelay(1);
  }
}
void StartTaskReceive(void const * argument)
{
  
	uint32_t rev;

  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
			{
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET)
			{
				//rev = ulTaskNotifyTake(pdTRUE,portMAX_DELAY);//当为pdTRUE的时候,模拟的为二值信号量
				rev = ulTaskNotifyTake(pdFALSE,portMAX_DELAY);//当为pdFALSE的时候,模拟的是计数型信号量
				if(rev != 0)
				//printf("任务通知:模拟二值信号量接收成功 !\r\n");
							printf("任务通知:模拟计数型信号量接收成功 ! rev=%d \r\n",rev);
			}
			while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1) == RESET);
			}
				
    osDelay(1);
  }
 
}

模拟计数型信号量实验结果:

模拟二值信号量结果:

2.模拟事件标志组和模拟邮箱

2.1模拟事件标志组

void StartTaskSend(void const * argument)
{
 
	uint16_t buf = 100;
	BaseType_t status;
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
		{
		osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
				{	
				printf("将bit0位置为1\r\n");
					xTaskNotify(taskReceiveHandle,0x01,eSetBits);
			}
				while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
		}
		
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
		{
		osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
				{	
				printf("将bit1位置为1\r\n");
					xTaskNotify(taskReceiveHandle,0x02,eSetBits);
			}
				while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
		}
    osDelay(10);
  }
  
}
void StartTaskRecive(void const * argument)
{

	uint32_t notify_val = 0, event_bit = 0;
 
  for(;;)
  {	
	xTaskNotifyWait(0,0XFFFFFFFF,&notify_val,portMAX_DELAY);
		if(notify_val & 0x01)
			event_bit |= 0x01;
		if(notify_val & 0x02)
			event_bit |= 0x02;
		if(event_bit == (0x01 | 0x02))
		{
			printf("任务通知模拟事件标志组接收成功!\r\n");
			event_bit = 0; 
		}
    osDelay(1);
  }

}

实验结果:

 2.2 模拟邮箱

StartTaskSend:

void StartTaskSend(void const * argument)
{
  
	uint16_t buf = 100;
	BaseType_t status;
 
  for(;;)
  {
		if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
		{
		osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET)
				{	
				printf("按键1按下\r\n");
					xTaskNotify(taskReceiveHandle,1,eSetValueWithOverwrite);//相比于事件标志组,改为了eSetValuewithOverwrit,ulValue变成了1
			}
				while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_RESET);
		}
		
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
		{
		osDelay(20);
			if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET)
				{	
				printf("按键2按下\r\n");
					xTaskNotify(taskReceiveHandle,2,eSetValueWithOverwrite);//eSetValueWithoutOverwrite相比于eSetValueWithOverwrite会复写,不影响最终实验结果
			}
				while(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_1)==GPIO_PIN_RESET);
		}
    osDelay(10);
  }
  
}

StartTaskRecive:

void StartTaskRecive(void const * argument)
{

	uint32_t notify_val = 0, event_bit = 0;

  for(;;)
  {	
	xTaskNotifyWait(0,0XFFFFFFFF,&notify_val,portMAX_DELAY);
		printf("接收到的通知值为:%d\r\n",notify_val);
    osDelay(1);
  }

}

实验结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/154847.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

UE5 - ArchvizExplorer - 数字孪生城市模板 -学习笔记(一)

1、学习资料 https://www.unrealengine.com/marketplace/zh-CN/product/archviz-explorer https://karldetroit.com/archviz-explorer-documentation/ 官网下载的是一个简单版,需要下载扩展,并拷贝到项目录下,才有完整版 https://drive.googl…

FileNotFoundError: Could not find module ‘XXX\lib\site-packages\llvmlite

https://aka.ms/vs/17/release/vc_redist.x64.exe 解决方法:安装c环境 FileNotFoundError: Could not find module xxx\workenv\lib\site-packages\llvmlite\binding\llvmlite.dll (or one of its dependencies). Try using the full path with constructor syntax. 装了个新…

NSS [SWPUCTF 2022 新生赛]1z_unserialize

NSS [SWPUCTF 2022 新生赛]1z_unserialize 我敲&#xff0c;报恩题&#xff01; 直接用构造方法构造POC更改$lt和$lly <?php class lyh{public $lt;public $lly;function __construct(){$this->lt"system";$this->lly"tac /flag";} } $a new…

Redis的发布和订阅

Redis发布订阅(pub/sub)是一种消息通信模式&#xff1a;发送者(pub)发送消息&#xff0c;订阅者(sub)接收消息。 Redis客户端可以订阅任意数量的频道。 举例说明&#xff0c;我们创建两个Redis客户端&#xff1a; 客户端1订阅channel1频道&#xff1a; 客户端2给channel1发送消…

ROS Turtlebot3多机器人编队导航仿真

文章目录 前言一、Gzazebo中加载多台Turtlebot3机器人二、RVIZ中加载多个Turtlebot3机器人三.多机器人编队导航总结 前言 前面已经实现了在gazebo仿真环境中机器人一字型编队、三角形编队、N字型编队等仿真&#xff0c;接下来考虑多机器人编队在编队行进过程中的避障问题&…

PON网络是什么

上节介绍到PON网络概念&#xff0c;PON网络具备节省局端光缆资源、避免故障点的同时&#xff0c;还具备拥有更远的传输距离、更高的带宽以及分光特性&#xff08;P2MP&#xff09;的优势。 PON&#xff08;无源光纤网络&#xff0c;Passive Optical Network&#xff09;网络&am…

uniapp 微信小程序分享功能 onShareAppMessage(options)

一、背景 在微信小程序中需要完成转发分享功能&#xff0c;接收人未登录小程序情况下&#xff0c;在微信上打开不用强制登录&#xff0c;可以查看部分分享的内容&#xff1b;如果用户要查看更多内容&#xff0c;可以点击【查看全部】按钮&#xff0c;触发登录逻辑&#xff0c;…

CodeMeter软件保护及授权管理解决方案(一)

概述 CodeMeter是德国威步&#xff08;Wibu-Systems AG&#xff09;2004年1月推出的软件加密及授权管理综合解决方案&#xff0c;用于软件保护实现防盗版、软件授权管理实现软件货币化、以及数据加密实现数字资产保护。 使用CodeMeter综合解决方案&#xff0c;可以实现以下价…

【开源】基于Vue和SpringBoot的用户画像活动推荐系统

项目编号&#xff1a; S 061 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S061&#xff0c;文末获取源码。} 项目编号&#xff1a;S061&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 兴趣标签模块2.3 活…

Linux Control Cgroups

无论 Docker 如何进行隔离&#xff0c;无法否认的是我们在当前宿主机中运行的所有容器&#xff0c;它依赖的硬件资源都只是当前机器。 其实启动的每一个容器进程&#xff0c;它本身其实就是当前宿主机的进程之一&#xff0c;那么本质上来说&#xff0c;它也会和宿主机中的其他…

HTML语言的由来与发展历程

HTML&#xff08;HyperText Markup Language&#xff09;是用来描述网页的一种语言&#xff0c;它的由来与发展历程可以追溯到20世纪90年代初。 1980年代初期&#xff0c;Tim Berners-Lee爵士在欧洲核子物理实验室&#xff08;CERN&#xff09;工作期间&#xff0c;开发了一种…

windows安装gdal库

提示&#xff1a;在windows上使用pip在cmd终端安装gdal 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤 1.引入库2.读入数据总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 原因是由于丹丹安装使用pip安装gdal时报错Microsoft visual C 1…

【左程云算法全讲11】贪心算法 并查集

系列综述&#xff1a; &#x1f49e;目的&#xff1a;本系列是个人整理为了秋招面试的&#xff0c;整理期间苛求每个知识点&#xff0c;平衡理解简易度与深入程度。 &#x1f970;来源&#xff1a;材料主要源于左程云算法课程进行的&#xff0c;每个知识点的修正和深入主要参考…

Maven编译报错:javacTask: 源发行版 1.8 需要目标发行版 1.8

报错截图&#xff1a; IDEA中的jdk检查都正常设置的1.8一点毛病没有。参考其他帖子链接如下&#xff1a; https://blog.csdn.net/zhishidi/article/details/131480199https://blog.51cto.com/u_16213460/7197764https://blog.csdn.net/lck_csdn/article/details/125387878 逐…

Android 13.0 recovery出厂时清理中字体大小的修改

1.前言 在13.0的系统rom定制化开发中,在recovery模块也是系统中比较重要的模块,比如恢复出厂设置,recovery ota升级, 清理缓存等等,在一些1080p的设备,但是density只是240这样的设备,会在恢复出厂设置的时候,显示的字体有点小, 产品要求需要将正在清理的字体调大点,这…

A Comprehensive Survey on Graph Neural Networks

A Comprehensive Survey on Graph Neural Networks----《图神经网络研究综述》 摘要 近年来&#xff0c;深度学习已经彻底改变了许多机器学习任务&#xff0c;从图像分类和视频处理到语音识别和自然语言理解。这些任务中的数据通常在欧几里得空间中表示。然而&#xff0c;越来…

个体诊所电子处方模板,佳易王药店电子处方系统门诊病历软件教程

个体诊所电子处方模板&#xff0c;佳易王药店电子处方系统门诊病历软件教程 软件支持中医&#xff0c;西医&#xff0c;对于经常使用的配方&#xff0c;可以自己设置配方模板&#xff0c;点击右侧 配方模板&#xff0c;选择后一键导入配方即可。处方单使用A5纸打印。软件可以试…

【OpenCV实现图像:OpenCV进行OCR字符分割】

文章目录 概要基本概念读入图像图像二值化小结 概要 在处理OCR&#xff08;Optical Character Recognition&#xff0c;光学字符识别&#xff09;时&#xff0c;利用传统的图像处理方法进行字符切分仍然是一种有效的途径。即便当前计算机视觉领域主导的是卷积神经网络&#xf…

【软考篇】中级软件设计师 第四部分(三)

中级软件设计师 第四部分&#xff08;三&#xff09; 三十四. 结构化开发方法34.1 内聚34.2 耦合 三十五. 测试基础知识三十六. 面向对象36.1 UML图36.2 设计模式36.3 数据流图 读前须知&#xff1a; 【软考篇】中级软件设计师 学前须知 上一章节&#xff1a; 【软考篇】中级软…

【入门篇】1.7 Redis 之 codis 入门介绍

文章目录 1. 简介2. Codis的安装与配置下载编译源码安装1. 安装 Go 运行环境2. 设置编译环境3. 下载 Codis 源代码4. 编译 Codis 源代码 Docker 部署 3. Codis的架构Codis的架构图和组件Codis的工作流程 4. Codis的核心特性自动数据分片数据迁移高可用性全面支持Redis命令分布式…