FreeRTOS——事件标志组

news2024/11/29 8:59:33

一、事件标志组

        前面所介绍的队列、信号量,只能实现与单个任务进行同步。而有时候某个任务可能需要与多个事件或任务进行同步,此时,事件标志组的作用就凸显出来

1.1 事件标志组简介

事件标志位:用一个位,来表示事件是否发生

事件标志组:一组事件标志位的集合, 可以简单的理解事件标志组,就是一个(16/32)整数

事件标志组是一种实现任务/中断间通信的机制,主要用于实现多任务间的同步

根据configUSE_16_BIT_TICKS 的宏定义不同,每个事件标志组的位数也就不同

        虽然使用了 32 位无符号的数据类型变量来存储事件标志, 但其中的8用作存储事件标志组的控制信息,低24位用作存储事件标志 ,所以说一个事件组最多可以存储 24 个事件标志

        可以发现,事件标志组与外设的状态寄存器SR非常类似,每一位都代表一个事件是否发生(高8位除外) 

1.2 事件标志组与队列、信号量的区别

此外:设置事件不会阻塞等待事件标志支持阻塞 

 

二、事件组结构体

typedef struct EventGroupDef_t
{
    EventBits_t uxEventBits;
    List_t xTasksWaitingForBits; /*< List of tasks waiting for a bit to be set. */

    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t uxEventGroupNumber;
    #endif

    /* 如果事件组是静态分配,则设置为pdTURE,以确保不尝试释放内存 */
    #if ( ( configSUPPORT_STATIC_ALLOCATION == 1 ) && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
        uint8_t ucStaticallyAllocated; /*< Set to pdTRUE if the event group is statically allocated to ensure no attempt is made to free the memory. */
    #endif
} EventGroup_t;
成员说明
uxEventBits

EventBits_t类型的变量,其中,

高八位:事件标志组的控制信息

剩余位:存储事件标志(1:发生;2:未发生)

xTasksWaitingForBits链表,等待事件标志位的任务的链表

三、相关API

函数

描述

xEventGroupCreate()

使用动态方式创建事件标志组

xEventGroupCreateStatic()

使用静态方式创建事件标志组

xEventGroupClearBits()

清零事件标志位

xEventGroupClearBitsFromISR()

在中断中清零事件标志位

xEventGroupSetBits()

设置事件标志位

xEventGroupSetBitsFromISR()

在中断中设置事件标志位

xEventGroupWaitBits()

等待事件标志位

xEventGroupSync()

设置事件标志位,并等待事件标志位

2.1 动态创建事件组

使用条件:configSUPPORT_DYNAMIC_ALLOCATION必须在 FreeRTOSConfig.h 中设置为 1,或保留未定义状态(此时默认为 1)

EventGroupHandle_t    xEventGroupCreate ( void ) ; 

返回值

描述

NULL

事件标志组创建失败

句柄

事件标志组创建成功

2.1.1 函数详解


#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )

    EventGroupHandle_t xEventGroupCreate( void )
    {
        /* 创建一个事件标志组结构体指针:pxEventBits */
        EventGroup_t * pxEventBits;


        /* 申请结构体空间,并将首地址赋给指针变量:pxEventBits */
        pxEventBits = ( EventGroup_t * ) pvPortMalloc( sizeof( EventGroup_t ) ); 


        /* 申请成功 */
        if( pxEventBits != NULL )
        {
            /* 将结构体中的时间标志组变量初始化为0*/
            pxEventBits->uxEventBits = 0;

            /* 初始化等待任务链表 */
            vListInitialise( &( pxEventBits->xTasksWaitingForBits ) );

            #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
            {
               
                pxEventBits->ucStaticallyAllocated = pdFALSE;
            }
            #endif /* configSUPPORT_STATIC_ALLOCATION */

            traceEVENT_GROUP_CREATE( pxEventBits );
        }


        /* 申请失败 */
        else
        {

            traceEVENT_GROUP_CREATE_FAILED(); 
        }

        /* 返回结构体的地址 */
        return pxEventBits;
    }

 2.1.2 函数实现总结

(1)创建一个时间标志组的结构体指针变量

(2)申请内存空间

        成功:将事件标志组变量初始化为0,并初始化等待事件标志任务列表

        失败:定义但未实现的宏

(3)返回:事件标志组的结构体指针变量

2.2 清除事件标志位

EventBits_t  xEventGroupClearBits( EventGroupHandle_t 	xEventGroup,				                                  
                                   const EventBits_t 	uxBitsToClear ) 

形参

描述

xEventGroup

待操作的事件标志组句柄

uxBitsToSet

待清零的事件标志位

返回值

描述

整数

清零事件标志位之前事件组中事件标志位的值

注:要清零的事件标志位,可以是一位,也可以是多位

0x08: 清除bit3

0x09:清除bit3和bit0

 2.3 设置事件标志位

EventBits_t   xEventGroupSetBits(  EventGroupHandle_t 	xEventGroup,					  
                                   const EventBits_t 		uxBitsToSet    ) 

形参

描述

xEventGroup

待操作的事件标志组句柄

uxBitsToSet

待设置的事件标志位 

返回值

描述

整数

函数返回时,事件组中的事件标志位值

注:要设置的事件标志位,可以是一位,也可以是多位

0x08: 设置bit3

0x09:设置bit3和bit0

2.4 获取事件标志组值

 

2.5 等待事件标志位

等待事件标志组的某些位被设置,选择性的进入阻塞状态,中断中无法调用此函数

EventBits_t   xEventGroupWaitBits(  EventGroupHandle_t 	xEventGroup,
                                 	const EventBits_t 	uxBitsToWaitFor,
                                 	const BaseType_t 	xClearOnExit,
                                 	const BaseType_t 	xWaitForAllBits,
                                 	TickType_t 		xTicksToWait     )

形参

描述

xEvenrGroup

等待的事件标志组句柄

uxBitsToWaitFor

等待的事件标志位,可以用逻辑或等待多个事件标志位

xClearOnExit

成功等待到事件标志位后,清除事件组中对应的事件标志位,

                pdTRUE  :清除uxBitsToWaitFor指定位;

                pdFALSE:不清除

xWaitForAllBits

等待 uxBitsToWaitFor 中的所有事件标志位(逻辑与)

pdTRUE:等待的位,全部为1     逻辑与

pdFALSE:等待的位,某个为1   逻辑或

xTicksToWait

等待的阻塞时间

返回值

描述

等待的事件标志位值

等待事件标志位成功,返回所等待到的事件标志位置1的事件标志组的值

其他值

等待事件标志位失败,返回事件组中的事件标志位

2.4.1 函数详解

EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToWaitFor,
                                 const BaseType_t xClearOnExit,
                                 const BaseType_t xWaitForAllBits,
                                 TickType_t xTicksToWait )
{

    /**
      * uxReturn:返回值(32位时间标志组变量)
      * uxControlBits:记录控制位信息(高八位)
      * xWaitConditionMet:记录等待条件是否已满足
      * xAlreadyYielded:记录调度器的状态
    */
    EventGroup_t * pxEventBits = xEventGroup;
    EventBits_t uxReturn, uxControlBits = 0;
    BaseType_t xWaitConditionMet, xAlreadyYielded;
    BaseType_t xTimeoutOccurred = pdFALSE;


    /* 检查用户没有去尝试等待内核本身使用的位(高8位),并且至少请求了一个位(低24位)。*/
    configASSERT( xEventGroup );
    configASSERT( ( uxBitsToWaitFor & eventEVENT_BITS_CONTROL_BYTES ) == 0 );
    configASSERT( uxBitsToWaitFor != 0 );

    #if ( ( INCLUDE_xTaskGetSchedulerState == 1 ) || ( configUSE_TIMERS == 1 ) )
    {
        configASSERT( !( ( xTaskGetSchedulerState() == taskSCHEDULER_SUSPENDED ) && ( xTicksToWait != 0 ) ) );
    }
    #endif


    /* 挂起调度器 */
    vTaskSuspendAll();
    {
        /* 取出结构体的32位变量,赋值给uxCurrentEventBits
        const EventBits_t uxCurrentEventBits = pxEventBits->uxEventBits;

        /* 检查是否以满足等待条件 */
        xWaitConditionMet = prvTestWaitCondition( uxCurrentEventBits, uxBitsToWaitFor, xWaitForAllBits );


         /* 等待条件已满足 */
        if( xWaitConditionMet != pdFALSE )
        {
            
            /* 将32变量赋给uxReturn,并将等待时间设置为0 */
            uxReturn = uxCurrentEventBits;
            xTicksToWait = ( TickType_t ) 0;

            /* 判断是否需要清除标志位 */
            if( xClearOnExit != pdFALSE )
            {
                pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }
        }

        /* 等待条件不满足,并且未设置等待时间 */
        else if( xTicksToWait == ( TickType_t ) 0 )
        {
            /* 返回当前32位变量,并将超时标志置为:pdTURE */
            uxReturn = uxCurrentEventBits;
            xTimeoutOccurred = pdTRUE;
        }

        /* 等待条件不满足 */
        else
        {
        
            /* 需要清除标志位,将第25位置1 */
            if( xClearOnExit != pdFALSE )
            {
                uxControlBits |= eventCLEAR_EVENTS_ON_EXIT_BIT;
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }

            
            /* 需要等待所有标志位 or 至少一个标志位,将第26位置1 */
            if( xWaitForAllBits != pdFALSE )
            {
                uxControlBits |= eventWAIT_FOR_ALL_BITS;
            }
            else
            {
                mtCOVERAGE_TEST_MARKER();
            }


            
            /* 此函数的功能:
            ** (1)控制位 | 等待的事件标志位 的结果,赋给列表项的值(用于升序排列)
            ** (2)将任务添加到等待事件组的列表中
            ** (3)将任务添加到阻塞列表中,任务进入阻塞状态
            */
            vTaskPlaceOnUnorderedEventList( &( pxEventBits->xTasksWaitingForBits ), ( uxBitsToWaitFor | uxControlBits ), xTicksToWait );

            /* 返回值赋为0 */
            uxReturn = 0;

            traceEVENT_GROUP_WAIT_BITS_BLOCK( xEventGroup, uxBitsToWaitFor );
        }
    }


    /* 恢复调度器 */
    xAlreadyYielded = xTaskResumeAll();

    if( xTicksToWait != ( TickType_t ) 0 )
    {
        if( xAlreadyYielded == pdFALSE )
        {
            portYIELD_WITHIN_API();
        }
        else
        {
            mtCOVERAGE_TEST_MARKER();
        }

        /* The task blocked to wait for its required bits to be set - at this
         * point either the required bits were set or the block time expired.  If
         * the required bits were set they will have been stored in the task's
         * event list item, and they should now be retrieved then cleared. */
        uxReturn = uxTaskResetEventItemValue();

        if( ( uxReturn & eventUNBLOCKED_DUE_TO_BIT_SET ) == ( EventBits_t ) 0 )
        {
            taskENTER_CRITICAL();
            {
                /* The task timed out, just return the current event bit value. */
                uxReturn = pxEventBits->uxEventBits;

                /* It is possible that the event bits were updated between this
                 * task leaving the Blocked state and running again. */
                if( prvTestWaitCondition( uxReturn, uxBitsToWaitFor, xWaitForAllBits ) != pdFALSE )
                {
                    if( xClearOnExit != pdFALSE )
                    {
                        pxEventBits->uxEventBits &= ~uxBitsToWaitFor;
                    }
                    else
                    {
                        mtCOVERAGE_TEST_MARKER();
                    }
                }
                else
                {
                    mtCOVERAGE_TEST_MARKER();
                }

                xTimeoutOccurred = pdTRUE;
            }
            taskEXIT_CRITICAL();
        }
        else
        {
            /* The task unblocked because the bits were set. */
        }

        /* The task blocked so control bits may have been set. */
        uxReturn &= ~eventEVENT_BITS_CONTROL_BYTES;
    }

    traceEVENT_GROUP_WAIT_BITS_END( xEventGroup, uxBitsToWaitFor, xTimeoutOccurred );

    /* Prevent compiler warnings when trace macros are not used. */
    ( void ) xTimeoutOccurred;

    return uxReturn;
}

2.6 同步函数

EventBits_t    xEventGroupSync(   EventGroupHandle_t 	xEventGroup,						 
                                  const EventBits_t 	uxBitsToSet,					
                                  const EventBits_t 	uxBitsToWaitFor,					
                                  TickType_t 		xTicksToWait) 

形参

描述

xEventGroup

等待事件标志所在事件组

uxBitsToSet

达到同步点后,要设置的事件标志

uxBitsToWaitFor

等待的事件标志

xTicksToWait

等待的阻塞时间,等待uxBitsToWaitFor参数值指定的 所有位设置完成的最长时间 

返回值

描述

等待的事件标志位值

等待事件标志位成功,返回等待到的事件标志位

其他值

等待事件标志位失败,返回事件组中的事件标志位

特点:通过设置某一位或多位(uxBitsToSet) ,等待标志位(uxBitsToWaitFor),即设置了uxBitsToSet,还需要等待uxBitsToWaitFor被设置才可以进行后续操作

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

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

相关文章

【C语言小知识】缓冲区

缓冲区 当我们使用printf()将数据显示在屏幕上&#xff0c;或者使用scanf()函数将数据输入到电脑里&#xff0c;我们是否会产生些许疑问&#xff1f;为何输入的字符会直接显示到屏幕上等等。这里需要介绍一个C语言中的一个关键概念——缓冲区。 当我们使用老式系统进行运行代码…

2024.8月28号杭州电商博览会,在杭州国博举办

2024杭州电商新渠道博览会暨集脉电商节 时间&#xff1a;2024年08月28-30日 地点&#xff1a;杭州国际博览中心&#xff08;G20&#xff09; 主办单位&#xff1a;浙江集脉展览有限公司、杭州华维展览有限公司 承办单位&#xff1a;浙江集脉展览有限公司 报名参展&#xf…

Python 编程快速上手——让繁琐工作自动化(第2版)读书笔记01 Python基础快速过关

Python 编程快速上手——让繁琐工作自动化&#xff08;第2版&#xff09;读书笔记01 Python基础快速过关 1 python基础概念 Python提供了高效的高级数据结构&#xff0c;还能简单有效地面向对象编程。 python运算符顺序 **——%——//——/——*——-——python中常见的数据…

【Linux】什么是进程间通信?方式有哪些?本质理解?

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

H5 Canvas实现转盘效果,控制指定数字

效果图 实现思路&#xff1a; 用Canvas画圆&#xff0c;然后再画扇形&#xff0c;然后中奖的开始用一张图片代替&#xff0c;点击的时候触发转动效果。 实现代码&#xff1a; <!DOCTYPE html> <html> <head><meta charset"utf-8"><tit…

开源六轴协作机械臂myCobot 280接入GPT4大模型!实现更复杂和智能化的任务

本文已经或者同济子豪兄作者授权对文章进行编辑和转载 引言 随着人工智能和机器人技术的快速发展&#xff0c;机械臂在工业、医疗和服务业等领域的应用越来越广泛。通过结合大模型和多模态AI&#xff0c;机械臂能够实现更加复杂和智能化的任务&#xff0c;提升了人机协作的效率…

孟德尔随机化 --痛风与酒精消耗量

写在前面 最近看了微信公众号&#xff0c;jimmy谈到生信与基础之间&#xff0c;个人觉得生信与基础技术是无高低之分的&#xff0c;本质上都是科研中为了证实结果的一个工具。生信的实质是用计算机分析数据&#xff0c;接触基础比较好&#xff0c;感觉是实验操作。分析上游为实…

ESD管ESD113-B1-02EL(S)国产替代型号ULC0342CDNH,ULC0321CDNH

雷卯型号全&#xff0c;能替代大量infineon型号。具体如下&#xff1a; 应用于3.3V高速信号静电保护器件&#xff0c;infineon的ESD113-B1-02EL(DFN1006)和ESD113-B1-02ELS(DFN0603)&#xff0c;交期长&#xff0c;价格高。已经有很多客户选雷卯的 ULC0342CDNH(DFN1006)&#…

RK3568平台(opencv篇)opencv处理图像视频

一.读取图像文件并展示 灰度图像&#xff1a; 灰度图需要用 8 位二进制来表示&#xff0c;取值范围是 0-255。用 0 表示 0&#xff08;黑色&#xff09;&#xff0c; 用 255 表示 1&#xff08;白色&#xff09;&#xff0c;取值越大表示该点越亮。 RGB 彩色图像&#xff1a;…

Keras实战之图像分类识别

文章目录 整体流程数据加载与预处理搭建网络模型优化网络模型学习率Drop-out操作权重初始化方法对比正则化加载模型进行测试 实战&#xff1a;利用Keras框架搭建神经网络模型实现基本图像分类识别&#xff0c;使用自己的数据集进行训练测试。 问&#xff1a;为什么选择Keras&am…

全网最详细的Appium自动化测试框架(一)环境搭建

一、环境搭建 1、安装python3 2、安装appium-destop 3 、安装python虚拟环境 ,安装依赖库 : pip install Appium-Python-Client pip install pytest 4、安装java brew install java 配置好环境变量 5、安装 android-platform-tools &#xff08;也可以用android sdk 工…

数据库概念题总结

1、 2、简述数据库设计过程中&#xff0c;每个设计阶段的任务 需求分析阶段&#xff1a;从现实业务中获取数据表单&#xff0c;报表等分析系统的数据特征&#xff0c;数据类型&#xff0c;数据约束描述系统的数据关系&#xff0c;数据处理要求建立系统的数据字典数据库设计…

C++11|包装器

目录 引入 一、function包装器 1.1包装器使用 1.2包装器解决类型复杂 二、bind包装器 引入 在我们学过的回调中&#xff0c;函数指针&#xff0c;仿函数&#xff0c;lambda都可以完成&#xff0c;但他们都有一个缺点&#xff0c;就是类型的推导复杂性&#xff0c;从而会…

【TORCH】绘制权重分布直方图,权重torch.fmod对torch.normal生成的随机数进行取模运算

要绘制上述代码中权重初始化的分布&#xff0c;可以分别展示每一层初始化权重的直方图。我们将用 torch.fmod 对 torch.normal 生成的随机数进行取模运算&#xff0c;确保权重值在 -2 到 2 之间。 含义解释 torch.normal(0, init_sd, size...)&#xff1a;生成服从均值为 0、…

编译Open Cascade(OCC)并使用C#进行开发

说明&#xff1a; VS版本&#xff1a;Visual Studio Community 2022系统&#xff1a;Windows 11 专业版23H2Open CASCADE&#xff1a;v7.7.0&#xff08;链接&#xff1a;https://pan.baidu.com/s/1-o1s4z3cjpYf5XkwhSDspQ?pwdp9i5提取码&#xff1a;p9i5&#xff09; 下载和…

【Kafka】Kafka生产者开启幂等性后报错:Cluster authorization failed.

文章目录 背景解决服务端配置ACL增加授权 背景 用户业务需求&#xff0c;需要开启生产者的幂等性&#xff0c;生产者加了配置&#xff1a;enable.idempotence true用户使用的集群开启了ACL认证&#xff1a;SASL_PLAINTEXT/SCRAM-SHA-512用户生产消息时报错&#xff1a;org.ap…

[笔记] 卷积 - 02 滤波器在时域的等效形式

1.讨论 这里主要对时域和频域的卷积运算的特征做了讨论&#xff0c;特别是狄拉克函数的物理意义。 关于狄拉克函数&#xff0c;参考这个帖子&#xff1a;https://zhuanlan.zhihu.com/p/345809392 1.狄拉克函数提到的好函数的基本特征是能够快速衰减&#xff0c;对吧&#xf…

VBA提取word表格内容到excel

这是一段提取word表格中部分内容的vb代码。 Sub 提取word表格() mypath ThisWorkbook.Path & "\"myname Dir(mypath & "*.doc*")n 4 index of rowsRange("A1:F1") Array("课程代码", "课程名称", "专业&…

云服务器在 Web 应用程序中作用

云服务器在Web应用程序中扮演着至关重要的角色&#xff0c;它不仅是现代Web应用程序的基石&#xff0c;还是推动业务发展和提升用户体验的关键技术之一。下面将详细探讨云服务器在Web应用程序中的重要作用及其优势。 首先&#xff0c;云服务器为Web应用程序提供了高度可扩展的…

蜂窝物联粮仓环境在线监测系统,确保粮食安全

在金黄的麦田里&#xff0c;每一粒小麦都承载着农民的辛勤与期待。为了保证这些宝贵粮食的品质与安全&#xff0c;储存环节显得尤为重要。传统的粮仓管理方式已难以满足现代粮食储存的需求&#xff0c;因此&#xff0c;引入智慧粮仓环境监控系统成为了必然的选择。 一、为何需…