FreeRTOS入门教程(任务通知)

文章目录

  • 前言
  • 一、什么是任务通知
  • 二、任务通知和队列,信号量的区别
  • 三、任务通知的优点和缺点
    • 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.hqwc.cn/news/219001.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Shell脚本:Linux Shell脚本学习指南(第三部分Shell高级)二

七、Shell Here String&#xff08;内嵌字符串&#xff0c;嵌入式字符串&#xff09; Here String 是《六、Shell Here Document&#xff08;内嵌文档/立即文档&#xff09;》的一个变种&#xff0c;它的用法如下&#xff1a; command <<< string command 是 Shell 命…

TikTok 将开源“云中和”边缘加速器

“从某种意义上说&#xff0c;我们正在努力破解云的骨干网&#xff0c;以造福于我们&#xff0c;”TikTok产品管理基础设施经理Vikram Siwach指出&#xff0c;他解释了该公司即将开源的“全球服务加速器”的好处&#xff0c;这是一个可编程的边缘平台&#xff0c;可将应用程序需…

单片机学习1——点亮一个LED灯

Keil软件编写程序&#xff1a; 特殊功能寄存器声明&#xff1a; #include<reg52.h>sbit LED P1^0;void main() {LED 0;while(1); } 代码说明&#xff1a; sbit 语句是特殊功能位声明。 生成HEX文件&#xff0c;这个文件是下载到单片机里的文件。Options for Target…

机器学习---贝叶斯网络与朴素贝叶斯

1. 贝叶斯法则 如何判定一个人是好人还是坏人&#xff1f; 当你无法准确的熟悉一个事物的本质时&#xff0c;你可以依靠与事物特定本质相关的事件出现的次数来判断 其本质属性的概率。如果你看到一个人总是做一些好事&#xff0c;那这个人就越可能是一个好人。 数学语言表达…

微机课设--汇编语言在51单片机上写一个四位十进制加法器

代码如下 KEYVAL EQU 30HKEYTM EQU 31HKEYSCAN EQU 32HDAT EQU 33HSCANLED EQU 37HS_DAT EQU 38HD_DAT EQU 39HR_DATL EQU 3AHR_DATH EQU 3BH CALFLAG EQU 3CHFLAG BIT 00HORG 0000HLJMP MAINORG 000BHLJMP T0ISRORG 0030HMAIN:MOV SP,#5FHMOV TMOD,#01HMOV TH0,#0D8HMOV TL0,…

win10+ vs2017用cmake编译geos3.5.1

参考教程&#xff1a;使用CMake编译Geos3.5.0_cmake geos-CSDN博客 注意事项&#xff1a; 报错&#xff1a;在使用cmake编译geos-3.5.1的时候&#xff0c;会出现报错&#xff1a; CMake Error at CMakeLists.txt:330 (include): include could not find load file GenerateSou…

makefile项目构建

makefile项目构建 OVERVIEW makefile项目构建1.概念2.make选项3.makefile语法&#xff08;1&#xff09;基本语法&#xff08;2&#xff09;系统与自定变量&#xff08;3&#xff09;常用函数&#xff08;4&#xff09;模式匹配与伪目标 4.makefile编译流程&#xff08;1&#…

【模板】KMP算法笔记

练习链接&#xff1a;【模板】KMP - 洛谷 题目&#xff1a; 输入 ABABABC ABA 输出 1 3 0 0 1 思路&#xff1a; 根据题意&#xff0c;用到的是KMP算法&#xff0c;KMP算法思想是通过一个一个匹配首字母的原理进行整个匹配效果&#xff0c;当某个首字母不匹配的时候&#x…

哲学家就餐问题

文章目录&#xff1a; 问题描述及分析一次错误的尝试解决方案一解决方案二 问题描述及分析 哲学家就餐问题规定了有5位哲学家正在进行思考和就餐两种活动。用餐在一个桌子上进行&#xff0c;桌子上面有5个盘子和5个叉子&#xff0c;按照循环的方式分配。 问题的约束条件&#…

Linux学习笔记之六(进程之间的管道通信和信号处理)

目录 1、管道通信1.1、无名管道1.1、有名管道 2、信号处理2.1、信号的种类和发送2.2、信号的接受和处理 1、管道通信 管道通信是一个设备中进程与进程之间通信的一种方式&#xff0c;分为无名管道和有名管道两种。前者只能用于有亲缘关系的进程之间的通信&#xff0c;如父子进…

扫描条形码到电脑:Barcode to pc 4.6.3 Crack

像专业人士一样使用条形码将条形码发送到 PC 排名第一的智能手机扫描应用程序 将条形码即时发送到计算机程序并自动执行任务的最简单方法 受到全球 500,000 多名用户的信赖 条形码到 PC&#xff1a;Wi-Fi 扫描仪应用程序&#xff0c;条码到 PC&#xff1a;适用于 Android 和 i…

WorkPlus即时通讯软件,以自主安全为底座,连接工作的一切

在当今竞争激烈的商业环境中&#xff0c;中大型企业对于移动办公平台的需求越来越迫切。在众多可选的平台中&#xff0c;WorkPlus凭借其高性价比和针对中大型企业的特色功能&#xff0c;成为了许多企业的首选。本文将为各位读者深度解析WorkPlus私有化部署的优势&#xff0c;带…