FreeRTOS入门教程(任务通知)

news2024/11/29 8:42:00

文章目录

  • 前言
  • 一、什么是任务通知
  • 二、任务通知和队列,信号量的区别
  • 三、任务通知的优点和缺点
    • 1.优点
    • 2.缺点
  • 四、任务状态和通知值
  • 五、任务通知相关的函数
    • 发出通知
    • 取出通知
  • 六、任务通知具体使用
    • 1.实现轻量级信号量
      • 二进制信号量
      • 计数型信号量
    • 2.实现轻量级队列
  • 总结


前言

本篇文章将带大家学习任务通知的概念和使用方法。

一、什么是任务通知

FreeRTOS中的任务通知(Task Notification)是一种轻量级的同步机制,允许一个任务通知另一个任务已发生的事件或条件。这对于多任务系统中的协作和同步非常有用。以下是有关FreeRTOS任务通知的详细讲解:

任务通知的作用:
任务通知的主要作用是允许一个任务通知其他任务已发生的事件,而无需使用更重的互斥锁或信号量。这可以用于线程间的通信和同步,以及处理任务之间的依赖关系。

通知值(Notification Value):
任务通知包括一个32位的通知值,用于传递信息。通知值可以是整数或位掩码,具体的含义由应用程序自行定义。任务可以等待特定的通知值或位掩码,以便在通知发生时采取相应的行动。

二、任务通知和队列,信号量的区别

任务通知、队列和信号量是FreeRTOS中用于任务间通信和同步的不同机制,它们有不同的特点和适用场景:

1.任务通知(Task Notification):

用途:任务通知主要用于任务之间的事件通知和同步,一个任务向其他任务发送通知,以表明某些事件已发生。
特点:轻量级、高效,通常用于一对一或一对多的任务通信。
通信方式:通知是无数据的,只包含一个32位的通知值,任务可以等待特定的通知值。
适用场景:适用于任务之间的事件通知、依赖关系、同步等情况,以及需要高效且快速的通信。

使用任务通知时发送方可以直接将发送信息给接收方,不需要通过中间的结构体对象(信号量,队列结构体)。
在这里插入图片描述

2.队列(Queue):

用途:队列用于任务之间的数据传递,允许一个任务发送数据给另一个任务。
特点:队列是有缓冲区的,可以传输多个数据元素,支持FIFO(先进先出)顺序。
通信方式:队列是带数据的通信机制,任务可以发送和接收数据。
适用场景:适用于需要任务之间传递数据的情况,如生产者-消费者问题、数据采集等。

3.信号量(Semaphore):

用途:信号量用于控制对共享资源的访问,允许任务对资源的使用进行同步和互斥。
特点:信号量通常用于资源保护和互斥访问,可以是二进制信号量(互斥锁)或计数信号量(资源计数)。
通信方式:信号量通常用于任务之间互斥,以确保只有一个任务可以访问共享资源。
适用场景:适用于共享资源的访问控制、互斥操作等情况,如保护共享内存、硬件设备等。

使用队列,信号量时都需要创建出通信对象结构体,通过这个结构体进行通信。
在这里插入图片描述

总的来说,任务通知适用于事件通知和轻量级的同步,队列适用于任务之间的数据传递,而信号量适用于资源访问的同步和互斥。在选择合适的通信和同步机制时,应根据具体需求和任务之间的关系来决定使用哪种机制。有时,这些机制也可以结合使用,以满足更复杂的任务间通信和同步需求。

三、任务通知的优点和缺点

1.优点

1.轻量级和高效: 任务通知是一种轻量级的通信机制,它不需要大量的内存和处理时间来维护,因此非常高效。

2.适用于一对多通信: 任务通知适用于一对多的任务通信,一个任务可以通知多个等待通知的任务,这在某些场景下非常有用。

3.实时性强: 任务通知可以提供较低的延迟,因为一旦通知被发送,接收通知的任务可以立即响应。

4.支持不同类型的通知: 任务通知可以发送不同类型的通知,任务可以等待特定的通知类型。

5.无需额外的资源: 与消息队列等机制不同,任务通知不需要为数据缓冲区分配额外的内存,因此它更节省资源。

2.缺点

1.无数据传递: 任务通知本身不支持数据传递,只能传递一个32位的通知值。如果需要传递数据,你可能需要结合其他机制来实现。

2.适用性有限: 任务通知更适用于简单的事件通知和同步需求,对于复杂的数据交换和同步需求,可能需要使用其他机制,如消息队列或信号量。

3.不适用于多生产者-多消费者问题: 任务通知通常不适合解决多生产者和多消费者问题,因为它不提供数据缓冲区来处理多个生产者和消费者之间的数据共享。

4.不适合长期阻塞: 任务通知通常用于短期同步,如果任务需要长期等待,其他机制如消息队列可能更合适。

总的来说,任务通知是一种非常高效的任务间通信机制,适用于简单的事件通知和同步需求,但对于复杂的数据传递和同步问题,可能需要结合其他FreeRTOS机制来实现。选择合适的通信机制应根据具体的应用需求来决定。

四、任务状态和通知值

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

一个是uint8 t类型,用来表示通知状态。

volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];

ucNotifyState[] 数组:

类型:volatile uint8_t
作用:通常用于存储任务通知的状态。
FreeRTOS允许任务等待多个通知。这个数组可能用于记录每个任务是否已经接收到通知,或者通知的处理状态。每个元素可能对应一个任务的通知状态。

任务通知的三种状态:

#define taskNOT_WAITING_NOTIFICATION              ( ( uint8_t ) 0 )

含义:任务处于未等待通知的状态。
初始状态或者任务已经完成了对通知的等待,准备进入下一个等待通知的周期。

#define taskWAITING_NOTIFICATION                  ( ( uint8_t ) 1 )

含义:任务正在等待通知的状态。
当任务调用 ulTaskNotifyTake 等待通知时,它的状态将变为等待通知状态。任务会一直保持在这个状态,直到它收到通知或者等待超时。

#define taskNOTIFICATION_RECEIVED                 ( ( uint8_t ) 2 )

含义:任务已经收到通知的状态。
当任务成功接收到通知时,其状态将从等待通知状态切换到通知已接收状态。任务可以通过调用 ulTaskNotifyTake 函数获取通知的值,并执行相应的操作。
一个是uint32 t类型,用来表示通知值。

volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];

ulNotifiedValue[] 数组:

类型:volatile uint32_t
作用:通常用于存储任务接收到的通知值。
每个任务都可以使用 ulTaskNotifyTake 函数等待通知,并在接收到通知时获得相应的值。这个数组可能被设计为记录多个任务接收到的通知值。数组的每个元素对应一个任务。

五、任务通知相关的函数

发出通知

发出通知有两个函数可以使用,分别是xTaskNotifyGive和xTaskNotify。

xTaskNotifyGive(TaskHandle_t xTaskToNotify);

功能:向指定的任务发送一个通知。
参数:xTaskToNotify 是要通知的任务的句柄(handle)。
返回值:无。
详细说明:这个函数用于向另一个任务发送通知。通知的具体内容可以是一个比特位或者一个32位的值,取决于任务通知的类型。被通知的任务可以通过 ulTaskNotifyTake 函数获取通知的值。

xTaskNotify(TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction)

功能:向指定的任务发送一个通知,可以指定通知的值和通知的行为。
参数:
xTaskToNotify:要通知的任务的句柄(handle)。
ulValue:通知的值,可以是一个比特位或者32位的值。
eAction:通知的行为,例如覆盖之前的通知值或者增加到之前的通知值。
返回值:无。
详细说明:这个函数允许发送带有值的通知,并且可以选择通知的行为。同样,被通知的任务可以通过 ulTaskNotifyTake 函数获取通知的值。

xTaskNotifyGive和xTaskNotify区别:

xTaskNotifyGive:
用途:向指定的任务发送一个通知,但不提供通知的具体值。
示例用法:xTaskNotifyGive(xTaskHandle);
适用情况:当通知的具体值不关键,只是为了触发目标任务执行某个操作时,使用此函数。

xTaskNotify:
用途:向指定的任务发送一个通知,可以指定通知的具体值和通知的行为。
示例用法:xTaskNotify(xTaskHandle, ulValue, eAction);
适用情况:当通知的具体值对于目标任务的操作非常重要时,或者需要更精细的控制通知的行为时,使用此函数。

取出通知

取出通知有两个函数可以使用,分别是ulTaskNotifyTake和xTaskNotifyWait。

ulTaskNotifyTake(BaseType_t xClearCountOnExit, TickType_t xTicksToWait);

功能:等待接收任务通知。
参数:
xClearCountOnExit:标志是否在任务等待通知时清零通知计数。
xTicksToWait:等待通知的超时时间。
返回值:接收到的通知的值。
详细说明:任务调用这个函数等待接收通知。如果在超时时间内收到通知,任务将返回通知的值;否则,返回0。通知的具体值和行为由前面的 xTaskNotify 函数设置。

xTaskNotifyWait(uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait);

功能:等待接收任务通知,并且可以设置在进入和退出时要清零的通知比特位。
参数:
ulBitsToClearOnEntry:进入等待通知时要清零的通知比特位。
ulBitsToClearOnExit:退出等待通知时要清零的通知比特位。
pulNotificationValue:指向接收到的通知值的指针。
xTicksToWait:等待通知的超时时间。
返回值:如果在超时时间内收到通知,返回 pdTRUE;否则,返回 pdFALSE。
详细说明:这个函数允许更加细粒度的控制,可以在进入和退出等待通知的时候清零通知的比特位。同样,被通知的任务可以通过 ulTaskNotifyTake 函数获取通知的值。

ulTaskNotifyTake和xTaskNotifyWait区别:

ulTaskNotifyTake:
用途:等待接收任务通知,返回接收到的通知的值。
示例用法:ulNotifiedValue = ulTaskNotifyTake(pdFALSE, xTicksToWait);
适用情况:当只需等待通知并获取其值时,使用此函数。通常用于轻量级的通知接收。

xTaskNotifyWait:
用途:等待接收任务通知,可以设置在进入和退出时要清零的通知比特位,返回是否在超时时间内收到通知。
示例用法:xResult = xTaskNotifyWait(ulBitsToClearOnEntry, ulBitsToClearOnExit, &ulNotificationValue, xTicksToWait);
适用情况:当需要更灵活的通知等待,并且需要在等待前后清零通知比特位时,使用此函数。通常用于更复杂的通知场景。

六、任务通知具体使用

1.实现轻量级信号量

xTaskNotifyGive函数可以让通知值加1,ulTaskNotifyTake可以让通知值减1,而且可以设置ulTaskNotifyTake的第一个参数来决定,是否清除通知值,设置为pdTURE则清除通知值(实现二进制信号量),设置为pdFALSE则不清除通知值(实现计数型信号量)。

二进制信号量

void Task1Function(void * param)
{
	volatile int i = 0;
	while (1)
	{
		for (i = 0; i < 10000; i++)
			sum++;
		//printf("1");
		for (i = 0; i < 10; i++)
		{
			// xSemaphoreGive(xSemCalc);
			xTaskNotifyGive(xHandleTask2);
		}
		vTaskDelete(NULL);
	}
}

void Task2Function(void * param)
{
	int i = 0;
	int val;
	while (1)
	{
		//if (flagCalcEnd)
		flagCalcEnd = 0;
		//xSemaphoreTake(xSemCalc, portMAX_DELAY);
		val = ulTaskNotifyTake(pdTURE, portMAX_DELAY);
		flagCalcEnd = 1;
		printf("sum = %d, NotifyVal = %d, i = %d\r\n", sum, val, i++);
	}
}

计数型信号量

void Task1Function(void * param)
{
	volatile int i = 0;
	while (1)
	{
		for (i = 0; i < 10000; i++)
			sum++;
		for (i = 0; i < 10; i++)
		{
			xTaskNotifyGive(xHandleTask2);
		}
		vTaskDelete(NULL);
	}
}

void Task2Function(void * param)
{
	int i = 0;
	int val;
	while (1)
	{
		val = ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
		printf("sum = %d, NotifyVal = %d, i = %d\r\n", sum, val, i++);
	}
}

2.实现轻量级队列

xTaskNotify和xTaskNotifyWait可以实现轻量级队列,用于传输一个uint32_t类型的数值。

void Task1Function(void * param)
{
	volatile int i = 0;
	while (1)
	{
		for (i = 0; i < 10000; i++)
			sum++;
		for (i = 0; i < 10; i++)
		{
			xTaskNotify(xHandleTask2, sum, eSetValueWithOverwrite);
			sum++;
		}
		vTaskDelete(NULL);
	}
}

void Task2Function(void * param)
{
	int val;
	int i = 0;
	
	while (1)
	{
		xTaskNotifyWait(0, 0, &val, portMAX_DELAY);
		printf("sum = %d, i = %d\r\n", val, i++);
	}
}

总结

本篇文章就讲解到这里,下篇文章继续讲解FreeRTOS中的内容。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Guitar Pro8.0.2吉他编曲软件 吉他打谱软件 吉他作曲软件

Guitar Pro8.0.2在音乐的大舞台上&#xff0c;谁不想成为一位吉他弹奏大师呢&#xff1f;但在现实中&#xff0c;学吉他并非一蹴而就&#xff0c;许多小伙伴都因为吉他的上手难度而被浇灭学习的热情。然而&#xff0c;这里有一款神奇的软件&#xff0c;叫做&#xff0c;它就像是…

C++双指针算法:统计点对的数目

本周推荐阅读 C二分算法&#xff1a;得到子序列的最少操作次数 本题其它解法 C二分查找&#xff1a;统计点对的数目 题目 给你一个无向图&#xff0c;无向图由整数 n &#xff0c;表示图中节点的数目&#xff0c;和 edges 组成&#xff0c;其中 edges[i] [ui, vi] 表示 u…

IO和NIO的区别 BIO,NIO,AIO 有什么区别? Files的常用方法都有哪些?

文章目录 IO和NIO的区别BIO,NIO,AIO 有什么区别?Files的常用方法都有哪些&#xff1f; 今天来对java中的io, nio, bio, aio进行了解&#xff0c;有何区别。 IO和NIO的区别 NIO与IO区别 IO是面向流的&#xff0c;NIO是面向缓冲区的Java IO面向流意味着每次从流中读一个或多个字…

【开源】基于Vue.js的快乐贩卖馆管理系统

项目编号&#xff1a; S 064 &#xff0c;文末获取源码。 \color{red}{项目编号&#xff1a;S064&#xff0c;文末获取源码。} 项目编号&#xff1a;S064&#xff0c;文末获取源码。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 搞笑视频模块2.3 视…

Java核心知识点整理大全15-笔记

Java核心知识点整理大全-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全2-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全3-笔记_希斯奎的博客-CSDN博客 Java核心知识点整理大全4-笔记-CSDN博客 Java核心知识点整理大全5-笔记-CSDN博客 Java核心知识点整理大全6…

steam搬砖还能做吗?CSGO饰品未来走势如何?

steam/csgo搬砖项目真能月入过万吗&#xff1f;到底真的假的&#xff1f; 如何看待CSGO饰品市场的整体走向&#xff1f; 从整体来说&#xff0c;CSGO的饰品市场与规模肯定会持续不断的上升&#xff0c;大盘不会发生特别大的波动&#xff0c;目前处于稳定期&#xff01;&#x…

elasticsearc DSL查询文档

文章目录 DSL查询文档DSL查询分类全文检索查询使用场景基本语法示例 精准查询term查询range查询总结 地理坐标查询矩形范围查询附近查询 复合查询相关性算分算分函数查询1&#xff09;语法说明2&#xff09;示例3&#xff09;小结 布尔查询1&#xff09;语法示例&#xff1a;2&…

C语言公交车之谜(ZZULIOJ1232:公交车之谜)

题目描述 听说郑州紫荆山公园有英语口语角&#xff0c;还有很多外国人呢。为了和老外对上几句&#xff0c;这周六早晨birdfly拉上同伴早早的就坐上了72路公交从学校向紫荆山进发。一路上没事干&#xff0c;birdfly开始思考一个问题。 从学校到紫荆山公园共有n(1<n<20)站路…

LeetCode Hot100 33.搜索旋转排序数组

题目&#xff1a; 整数数组 nums 按升序排列&#xff0c;数组中的值 互不相同 。 在传递给函数之前&#xff0c;nums 在预先未知的某个下标 k&#xff08;0 < k < nums.length&#xff09;上进行了 旋转&#xff0c;使数组变为 [nums[k], nums[k1], ..., nums[n-1], nu…

Docker Swarm总结+基础、集群搭建维护、安全以及集群容灾(1/4)

博主介绍&#xff1a;Java领域优质创作者,博客之星城市赛道TOP20、专注于前端流行技术框架、Java后端技术领域、项目实战运维以及GIS地理信息领域。 &#x1f345;文末获取源码下载地址&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3fb;…

C#,《小白学程序》第二十课:大数的加法(BigInteger Add)

大数的&#xff08;加减乘除&#xff09;四则运算、阶乘运算。 乘法计算包括小学生算法、Karatsuba和Toom-Cook3算法。 重复了部分 19 课的代码。 1 文本格式 using System; using System.Linq; using System.Text; using System.Collections.Generic; /// <summary>…

网络视频播放卡顿原因分析

一、问题描述 某项目通过拉摄像机rtsp流转rtmp/http-flv/ws-flv的方案&#xff0c;使用户可以在网页中观看摄像机的视频画面。在 观看视频时偶发出现卡顿现象。 二、卡顿现象分析和解决 此问题涉及的原因较多&#xff0c;所以得考虑各环节的问题可能性&#xff0c;并根据现场实…

C语言盐水的故事(ZZULIOJ1214:盐水的故事)

题目描述 挂盐水的时候&#xff0c;如果滴起来有规律&#xff0c;先是滴一滴&#xff0c;停一下&#xff1b;然后滴二滴&#xff0c;停一 下&#xff1b;再滴三滴&#xff0c;停一下...&#xff0c;现在有一个问题&#xff1a;这瓶盐水一共有VUL毫升&#xff0c;每一滴是D毫升&…

黑马点评-Feed流的实现方案,基于推拉结合模式实现笔记推送

Feed流实现方案 我们关注了博主之后,当用户发布了动态后我们应该把这些数据推送给粉丝,关注推送也叫作Feed(投喂)流,通过无限下拉刷新获取新的信息 传统的模式内容检索: 粉丝需要主动通过搜索引擎或者是其他方式去查找想看的内容新型Feed流的效果: 系统分析用户到底想看什么,…

CSDN C4模拟题

《计算机常识》 进制转换 一、任务目标 理解二进制/八进制/十进制/十六进制的原理 掌握各种不同的进制间的转换方法 二、任务背景 进制转换是软件工程师的必备技能,也是C1阶段的计算机通识模块之一,实际开发中的多媒体数据采集、分割、压缩、编解转码、传输、纠错、合并等…

队列详解(C语言实现)

文章目录 写在前面1 队列的定义2 队列的初始化3 数据入队列4 数据出队列5 获取队头元素6 获取队尾元素7 获取队列元素个数8 判断队列是否为空8 队列的销毁 写在前面 本片文章详细介绍了另外两种存储逻辑关系为 “一对一” 的数据结构——栈和队列中的队列&#xff0c;并使用C语…

WorkPlus稳定服务助力行业千万用户,打造无界沟通协作平台

在企业移动数字化领域&#xff0c;WorkPlus以其十年如一日的研发实力和千万级用户案例&#xff0c;成为众多企业首选的移动数字化平台。究竟是什么样的力量支撑着WorkPlus在市场上占据如此重要的地位呢&#xff1f;接下来&#xff0c;让我们一起揭开WorkPlus的神秘面纱&#xf…

【开源】基于Vue.js的陕西非物质文化遗产网站

文末获取源码&#xff0c;项目编号&#xff1a; S 065 。 \color{red}{文末获取源码&#xff0c;项目编号&#xff1a;S065。} 文末获取源码&#xff0c;项目编号&#xff1a;S065。 目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 设计目标2.2 研究内容2.3 研究方法与…

网络唤醒原理浅析(Wake On LAN)

原理 将唤醒魔术包发送的被唤醒机器的网卡上&#xff0c;魔术包指AMD公司开发的唤醒数据包&#xff0c;具有远程唤醒的网卡都支持这个标准&#xff0c;用16进制表示如下&#xff1a; 6对“FF”前缀16次重复MAC地址,举个例子假如我的网卡MAC地址是&#xff1a;AA:BB:CC:DD:EE:…

现代 C++ 函数式编程指南

现代 C 函数式编程指南 什么是 柯里化 &#xff08;Curry&#xff09;什么是 部分应用 &#xff08;Partial Application&#xff09; 二元函数 &#xff08;Partial Application&#xff09;参数排序 &#xff08;Partial Application&#xff09; 应用场景 计算碳衰减周期求年…