17. FreeRTOS 直接任务通知取代取代二进制信号量

2024-06-05 08:20

本文主要是介绍17. FreeRTOS 直接任务通知取代取代二进制信号量,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

FreeRTOS 直接任务通知取代取代二进制信号量

在 FreeRTOS 中,任务之间的同步和通信通常通过信号量(Semaphore)来实现。其中,二进制信号量是一种简单的同步工具,用于指示某个事件的发生。然而,FreeRTOS 提供了一种更高效的替代方案:直接任务通知(Direct Task Notification)。

为什么选择直接任务通知?

直接任务通知可以用来替代二进制信号量在任务之间进行同步和简单的事件通知。这个方法有很多好处,比如占用更少内存:直接任务通知与任务控制块(TCB)直接相关,不需要额外的内存分配,而二进制信号量则需要额外的信号量控制块。更高效:直接任务通知避免了信号量获取和释放的开销,直接修改任务的内部状态,提高了性能。更简洁:直接任务通知提供了简洁的 API 调用,减少了代码的复杂性。

🚨需要注意直接任务通知在FreeRTOS中是个高效的任务间通信方法,但它并不能替代所有情况下的二进制信号量。尤其是在多个任务需要等待同一事件、复杂同步、递归信号量以及一些中断处理时,二进制信号量还是更合适的选择。每种工具都有其独特的用武之地,灵活运用才能让系统更可靠高效。

示例:使用直接任务通知替代二进制信号量

下面的示例展示了如何使用直接任务通知来替代二进制信号量,实现两个任务间的同步。

#include <Arduino.h>
#include <FreeRTOS.h>
#include <task.h>TaskHandle_t xTask1Handle = NULL;
TaskHandle_t xTask2Handle = NULL;// 任务1:等待任务
void Task1(void *pvParameters) {while (1) {// 等待任务通知ulTaskNotifyTake(pdTRUE, portMAX_DELAY);// 执行任务Serial.println("Task1 is running");// 模拟任务处理时间vTaskDelay(pdMS_TO_TICKS(1000));}
}// 任务2:通知任务
void Task2(void *pvParameters) {while (1) {// 延迟2秒vTaskDelay(pdMS_TO_TICKS(2000));// 发送任务通知xTaskNotifyGive(xTask1Handle);Serial.println("Notification sent to Task1");}
}void setup() {Serial.begin(115200);// 创建任务1xTaskCreate(Task1, "Task1", 1024, NULL, 1, &xTask1Handle);// 创建任务2xTaskCreate(Task2, "Task2", 1024, NULL, 1, &xTask2Handle);
}void loop() {// 空的loop函数
}
  1. Task1:等着收任务通知,一接到通知就打印一条消息,然后模拟处理任务。
    • ulTaskNotifyTake(pdTRUE, portMAX_DELAY) 这个函数用来等待任务通知,等收到通知后就清除通知计数。
  2. Task2:每过2秒就给任务1发一次通知。
    • xTaskNotifyGive(xTask1Handle) 这个函数用来给任务1发送通知。

在这个例子里,Task1Task2 通过直接任务通知来同步。Task2 每2秒就给Task1发一次通知,Task1 在收到通知后就执行任务处理。这样就用直接任务通知代替了二进制信号量,实现了任务之间高效的同步机制。

直接任务通知 API 简介

ulTaskNotifyTake

uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
  • xClearCountOnExit:当为 pdTRUE 时,通知值在退出时会被清除;为 pdFALSE 时,通知值在退出时不会被清除。
  • xTicksToWait:任务等待通知的最大时间,可以是指定的时间(以tick为单位)或 portMAX_DELAY(表示无限等待)。

xTaskNotifyGive

BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
  • xTaskToNotify:要通知的任务句柄。

这两个 API 用起来简单轻松,让任务间的沟通变得爽快又顺畅,代码也变得简洁明了。让任务同步变得更直观高效。

总结

FreeRTOS 的直接任务通知为任务间的同步提供了一种更高效、更简洁的机制。相比于传统的二进制信号量,直接任务通知减少了内存开销和处理开销,极大地提高了系统的性能和可靠性。

这篇关于17. FreeRTOS 直接任务通知取代取代二进制信号量的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1032554

相关文章

FreeRTOS-基本介绍和移植STM32

FreeRTOS-基本介绍和STM32移植 一、裸机开发和操作系统开发介绍二、任务调度和任务状态介绍2.1 任务调度2.1.1 抢占式调度2.1.2 时间片调度 2.2 任务状态 三、FreeRTOS源码和移植STM323.1 FreeRTOS源码3.2 FreeRTOS移植STM323.2.1 代码移植3.2.2 时钟中断配置 一、裸机开发和操作系统开发介绍 裸机:前后台系

FreeRTOS内部机制学习03(事件组内部机制)

文章目录 事件组使用的场景事件组的核心以及Set事件API做的事情事件组的特殊之处事件组为什么不关闭中断xEventGroupSetBitsFromISR内部是怎么做的? 事件组使用的场景 学校组织秋游,组长在等待: 张三:我到了 李四:我到了 王五:我到了 组长说:好,大家都到齐了,出发! 秋游回来第二天就要提交一篇心得报告,组长在焦急等待:张三、李四、王五谁先写好就交谁的

FreeRTOS学习笔记(六)队列

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、队列的基本内容1.1 队列的引入1.2 FreeRTOS 队列的功能与作用1.3 队列的结构体1.4 队列的使用流程 二、相关API详解2.1 xQueueCreate2.2 xQueueSend2.3 xQueueReceive2.4 xQueueSendFromISR2.5 xQueueRecei

FreeRTOS学习笔记(二)任务基础篇

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、 任务的基本内容1.1 任务的基本特点1.2 任务的状态1.3 任务控制块——任务的“身份证” 二、 任务的实现2.1 定义任务函数2.2 创建任务2.3 启动任务调度器2.4 任务的运行与切换2.4.1 利用延时函数2.4.2 利用中断 2.5 任务的通信与同步2.6 任务的删除2.7 任务的通知2

Flink任务重启策略

概述 Flink支持不同的重启策略,以在故障发生时控制作业如何重启集群在启动时会伴随一个默认的重启策略,在没有定义具体重启策略时会使用该默认策略。如果在工作提交时指定了一个重启策略,该策略会覆盖集群的默认策略默认的重启策略可以通过 Flink 的配置文件 flink-conf.yaml 指定。配置参数 restart-strategy 定义了哪个策略被使用。常用的重启策略: 固定间隔 (Fixe

第49课 Scratch入门篇:骇客任务背景特效

骇客任务背景特效 故事背景:   骇客帝国特色背景在黑色中慢慢滚动着! 程序原理:  1 、 角色的设计技巧  2 、克隆体的应用及特效的使用 开始编程   1、使用 黑色的背景: ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/7d74c872f06b4d9fbc88aecee634b074.png#pic_center)   2

FreeRTOS学习笔记(四)Freertos的中断管理及临界保护

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Cortex-M 中断管理1.1 中断优先级分组1.2 相关寄存器1.3 相关宏定义1.4 FreeRTOS 开关中断 二、临界段及其保护2.1 taskENTER_CRITICAL( ) 和 taskEXIT_CRITICAL( )2.2 taskENTER_CRITICAL_FROM_ISR( )

通信工程学习:什么是2ASK/BASK二进制振幅键控

2ASK/BASK:二进制振幅键控         2ASK/BASK二进制振幅键控是一种数字调制技术,其全称是二进制振幅键控(Binary Amplitude Shift Keying)。该技术通过改变载波的振幅来传递二进制数字信息,而载波的频率和相位则保持不变。以下是关于2ASK/BASK二进制振幅键控的详细解释: 一、2ASK/BASK二进制振幅键控的基本原理 1、振幅键控:

AsyncTask 异步任务解析

1:构建AsyncTask 子类的回调方法: A:doInBackground:   必须重写,所有的耗时操作都在这个里面进行; B: onPreExecute:     用户操作数据前的调用; 例如:显示一个进度条 等 ; C: onPostExecute:    当doInBackground 执行完成后;会自动把数据传给onPostExecute方法;也就是说:这个方法是处理返回的数据的方法

17 通过ref代替DOM用来获取元素和组件的引用

重点 ref :官网给出的解释是: ref: 用于注册对元素或子组件的引用。引用将在父组件的$refs 对象下注册。如果在普通DOM元素上使用,则引用将是该元素;如果在子组件上使用,则引用将是组件实例: <!-- vm.$refs.p will be the DOM node --><p ref="p">hello</p><!-- vm.$refs.child will be the c