ThreadX——IPC应用之事件标志

发布者:闪耀星空最新更新时间:2025-02-28 来源: cnblogs关键字:ThreadX 手机看文章 扫描二维码
随时随地手机看文章

一、应用简介

RTOS的应用开发中,事件标志主要是用来进行任务之间的事件通知。例如有A和B两个任务,A任务负责接收消息,B任务负责对消息响应。当A任务接收到消息后设置响应标志,B任务监测到响应标志被设置就执行消息响应。事件标志没被设置的时候任务是不会占用CPU的,不用像裸机程序那样不断轮询事件的发生,使得CPU的利用率更高,这也是使用RTOS的优势之一。


二、API说明

下面列出使用事件标志组时常用的几个函数


1、创建事件标志组

描述:

该函数会创建一个包含32个事件标志的事件组(其实就是一个32bit的变量),组中的32个事件标志都被初始化为零,每个事件标志由一个Bit表示(bit位置1则表明该位代表的事件标志被设置)。

参数

group_ptr :指向事件标志组控件块的指针

name_ptr :指向事件标志组名称的指针

返回值

TX_SUCCESS (0x00) :成功创建事件组

TX_GROUP_ERROR (0x06) :无效的事件组指针,指针为NULL或事件组已创建

TX_CALLER_ERROR (0x13):该服务的调用者无效

UINT tx_event_flags_create(

    TX_EVENT_FLAGS_GROUP *group_ptr,

    CHAR *name_ptr);

2、删除事件标志组

描述

此服务会删除指定的事件标志组,所有等待该组事件的挂起线程将被恢复,并给出TX_DELETED返回状态。

在删除事件标志组之前,应用程序必须确保完成(或禁用)此事件标志组的通知回调。此外,应用程序必须禁止使用已删除的事件标志组。

参数

group_ptr :指向先前创建的事件标志组的指针

返回值

TX_SUCCESS (0x00):成功删除事件标志组

TX_GROUP_ERROR (0x06):无效的事件标志组指针

TX_CALLER_ERROR (0x13):该服务的调用者无效

UINT tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr);

3、获取事件标志

描述

此服务从指定的事件标志组检索事件标志。每个事件标志组包含32个事件标志。每个标志由一个位表示。此服务可以检索由输入参数选择的各种事件标志组合。

参数

group_ptr:指向先前创建的事件标志组的指针

requested_flags:表示请求的事件标志

get_option:请求事件标志的选项(TX_AND (0x02):指定的事件标志必须全部有效;TX_OR (0x00):指定的事件部分部分有效即可;TX_AND_CLEAR (0x03):指定的事件标志必须都被设置且清除相应的事件标志;TX_OR_CLEAR (0x01):指定的事件标志部分被设置就满足条件且清除相应的事件标志)

actual_flags_ptr:指向放置检索到的事件标志的指针。请注意,获得的实际标志可能包含未被请求的标志。

wait_option:所选事件标志未被设置时服务的行为(TX_NO_WAIT (0x00000000) :不等待立即返回;TX_WAIT_FOREVER(0xFFFFFFFF):一直挂起等待直到事件标志被设置;(0x00000001 到 0xFFFFFFFE):等待的心跳节拍数,例如设置心跳是1KHZ那单位就是ms)

返回值

TX_SUCCESS(0x00)成功获得事件标志。

TX_DELETED(0x01)线程挂起时,事件标志组已删除。

TX_NO_EVENTS(0x07)服务无法在指定的等待时间内获取指定的事件。

TX_WAIT_ABORTED(0x1A)被另一个线程、计时器或中断服务打断。

TX_GROUP_ERROR(0x06)无效的事件标志组指针。

TX_PTR_ERROR(0x03)实际事件标志的无效指针。

TX_WAIT_ERROR(0x04)在非线程调用中指定了TX_NO_WAIT以外的等待选项。

TX_OPTION_ERROR(0x08)指定了无效的获取选项。

UINT tx_event_flags_get(

    TX_EVENT_FLAGS_GROUP *group_ptr,

    ULONG requested_flags, 

    UINT get_option,

    ULONG *actual_flags_ptr, 

    ULONG wait_option);

4、设置事件标志

描述

此服务根据指定的选项设置或清除事件标志组中的事件标志。 所有请求被设置事件标志的线程将从挂起状态恢复运行态。

参数

group_ptr:指向先前创建的事件标志组控制块的指针

flags_to_set:根据选择的设置选项指定要设置或清除的事件标志

set_option:将指定的事件标志与该组的当前事件标志进行“与”或“或”运算(TX_AND(0x02)、TX_OR(0x00));选择TX_AND将指定的事件标志与该组中的当前事件标志进行“与”运算。 此选项通常用于清除组中的事件标志。选择TX_OR,则将指定的事件标志与组中的当前事件进行“或”运算。

返回值

TX_SUCCESS(0x00)事件标志成功设置。

TX_GROUP_ERROR(0x06)指向事件标志组指针无效。

TX_OPTION_ERROR(0x08)指定了无效的设置选项。

UINT tx_event_flags_set(

    TX_EVENT_FLAGS_GROUP *group_ptr,

    ULONG flags_to_set,

    UINT set_option);

三、实例说明

该实例创建一个事件标志组和三个任务。标志组中包含了两个事件标志,任务1检测按键1的运行,任务2检测按键2的运行,任务3执行对应的按键响应,任务之间的通知采用事件标志的方式。


#include 'main.h'

#include 'usart.h'

#include 'gpio.h'

#include 'tx_api.h'


#define DEMO_STACK_SIZE         (2 * 1024)

#define DEMO_BYTE_POOL_SIZE     (32 * 1024)

/*事件标志*/

#define TX_EVENT_FLAG_KEY1 (1 << 0)

#define TX_EVENT_FLAG_KEY2 (1 << 1)


TX_THREAD               thread_0;

TX_THREAD               thread_1;

TX_THREAD               thread_2;


TX_BYTE_POOL            byte_pool_0;

UCHAR                   memory_area[DEMO_BYTE_POOL_SIZE];

/*事件标志组*/

TX_EVENT_FLAGS_GROUP tx_event_flags;


void    thread_0_entry(ULONG thread_input);

void    thread_1_entry(ULONG thread_input);

void    thread_2_entry(ULONG thread_input);


int main(void)

{

    HAL_Init();

    SystemClock_Config();

    MX_GPIO_Init();

    MX_USART1_UART_Init();


    tx_kernel_enter();

    while (1)

    {

    }

}


void tx_application_define(void *first_unused_memory)

{

    CHAR    *pointer = TX_NULL;


    /* Create a byte memory pool from which to allocate the thread stacks.  */

    tx_byte_pool_create(&byte_pool_0, 'byte pool 0', memory_area, DEMO_BYTE_POOL_SIZE);


    /* 创建事件标志组 */

    tx_event_flags_create(&tx_event_flags, 'my_event_group_name');


    /* Allocate the stack for thread 0.  */

    tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);

    /* Create the main thread.  */

    tx_thread_create(&thread_0, 'thread 0', thread_0_entry, 0,  

                    pointer, DEMO_STACK_SIZE, 

                    1, 1, TX_NO_TIME_SLICE, TX_AUTO_START);


    /* Allocate the stack for thread 1.  */

    tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);

    /* Create threads 1  */

    tx_thread_create(&thread_1, 'thread 1', thread_1_entry, 0,  

                    pointer, DEMO_STACK_SIZE, 

                    2, 2, TX_NO_TIME_SLICE, TX_AUTO_START);


    /* Allocate the stack for thread 2.  */

    tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT);

    /* Create threads 1  */

    tx_thread_create(&thread_2, 'thread 2', thread_2_entry, 0,  

                    pointer, DEMO_STACK_SIZE, 

                    3, 3, TX_NO_TIME_SLICE, TX_AUTO_START);

}


void    thread_0_entry(ULONG thread_input)

{

    uint8_t key_cnt = 0;


    while(1)

    {

        if (HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) != GPIO_PIN_RESET)

        {

            key_cnt++;

        }

        else

        {

            if (key_cnt > 2)

            {

                /* 按键1触发,设置事件标志 */

                tx_event_flags_set(&tx_event_flags, TX_EVENT_FLAG_KEY1, TX_OR);

            }

            key_cnt = 0;

        }


        tx_thread_sleep(20);

    }

}


void    thread_1_entry(ULONG thread_input)

{

    uint8_t key_cnt = 0;


    while(1)

    {

        if (HAL_GPIO_ReadPin(KEY2_GPIO_Port, KEY2_Pin) != GPIO_PIN_RESET)

        {

            key_cnt++;

        }

        else

        {

            if (key_cnt > 2)

            {

                /* 按键2触发,设置事件标志 */

                tx_event_flags_set(&tx_event_flags, TX_EVENT_FLAG_KEY2, TX_OR);

            }

            key_cnt = 0;

        }


        tx_thread_sleep(20);

    }

}


void    thread_2_entry(ULONG thread_input)

{

    UINT status;

    ULONG actual_events;


    while(1)

    {

        /* 等待事件标志:任意按键触发都有效 */

        status = tx_event_flags_get(&tx_event_flags, TX_EVENT_FLAG_KEY1 | TX_EVENT_FLAG_KEY2, TX_OR_CLEAR, &actual_events, TX_WAIT_FOREVER);


        if (TX_SUCCESS == status)

        {

            if (TX_EVENT_FLAG_KEY1 == (actual_events & TX_EVENT_FLAG_KEY1))

            {

                HAL_GPIO_TogglePin(LED1_GPIO_Port,LED1_Pin);

                printf('key1 is pressed, actual_events:0x%xrn', (int)actual_events);

            }


            if (TX_EVENT_FLAG_KEY2 == (actual_events & TX_EVENT_FLAG_KEY2))

            {

                HAL_GPIO_TogglePin(LED2_GPIO_Port,LED2_Pin);

                printf('key2 is pressed, actual_events:0x%xrn', (int)actual_events);

            }

        }

    }

}


效果如下:


关键字:ThreadX 引用地址:ThreadX——IPC应用之事件标志

上一篇:ThreadX——IPC应用之信号量
下一篇:ThreadX移植——STM32H7+MDK-AC6平台

推荐阅读最新更新时间:2026-03-25 11:52

回顾2013年在线医疗4大标志事件
    2013年见证了数字医疗的飞速发展,医疗健康是硅谷创业中最为热门的选项,截止第三季度末,共收获高达15亿美元的投资。奥巴马平价医疗法案ACA也刺激更多创业者投入医疗改革创业的热潮。这一年医生似乎比此前都更乐意接受数字医疗的新技术,联邦政府也在相关网站HealthIT.gov上发出关于“发挥电子医疗记录等先进手段的有效应用”的号召,将纸质病例记录换成电子版的医生可以通过邮件接受大宗支票。     但也不全是好消息:奥巴马政府新推出的HealthCare.gov门户网站问题频发,个人基因筛查项目23andMe被FDA禁止,三星推出的智能手表表现平平。在这些消息中,我们挑选了以下内容作为2013年科技健康类消息的代表性头条。
[医疗电子]
LPS音频功放选型及其在IPC应用
随着语音播放、交互功能的不断普及,在各类民用电子产品中,音频模块越来越成为必备的一部分。由于音频部分直接影响终端客户的使用体验,音频功放的设计也需要进行更多的考虑和取舍。市面上产品琳琅满目,各类产品的功能要求和侧重点也不尽相同,设计者需要根据具体应用选择最合适的音频放大器方案,熟悉各种可用的音频放大器类型及其特征也非常重要。以下是一些音频功放的选用要点,帮助您进一步了解其相关的选型和设计。 01 音频功放类型 A类:失真最小,静点工作电流最大,效率最低。 B类:失真较大,静点工作电流最小,效率较高。 AB类:失真中等,静点工作电流中等,效率中等,如LPA4890,LPA4891。 D类:工作原理完全不同的放大器,也称之为数
[嵌入式]
LPS音频功放选型及其在<font color='red'>IPC</font>的<font color='red'>应用</font>
IPC摄像机的智能化发展现状及应用趋势
    通过一台设备集成智能、IP、IT等诸多高科技技术与一身,设定多种智能分析策略,联动多种周边外设,形成一个完整的智能系统,对多种场景、多个事件进行自动侦测和提前预警,一定程度上做到事前预防,操作简单,不需要专用的智能平台软件,直接登录IE或客户端即可配置,例如天地伟业的智能分析只需要在IE中打钩开下侦测功能就可以实现。     随着IPC市场份额的逐年放量,高清已经得到普及并形成一套完整的解决方案。而随着智能化、高清化、平台化三驾马车的发力,基于端到端的智能高清平台已经初具规模,IPC智能化的时代已经到来。那么IPC智能化应用的现状以及未来趋势将朝着什么方向发展呢?     一、IPC发展现状     目前市面上
[安防电子]
IPC网络摄像机广泛应用于多个领域 优势明显
    随着社会经济的发展,IPC网络摄像机作为新一代的网络监控设备受到了肯定与青睐,除了提供高速的网络接入外还能取代同轴电缆图像传输线路,将实时图像监控纳入宽带信息网络应用范围,这就使得信息网络代替传统闭路电视成为必然。       IPC网络摄像机在视频监控领域的地位      IPC网络摄像机无疑是现今视频监控领域的第一大主题:一方面,电子、网络技术的快速发展大大提升了其应用价值和适用范围;另一方面,全球安防需求的急速膨胀以及用户越来越高的使用要求也极大刺激了网络摄像机的发展。      IPC网络摄像机只要插在网线上就能用,无需电脑配合,无须视频采集卡,没有监控局域限制,在任何地方打开网页就能监控,并支持12个客户端同时监控
[安防电子]
宽动态视频监控技术历经变革 看好高清IPC应用
    宽动态是应对强逆光监控的一个统称,大部分监控摄像机宽动态功能和强光抑制功能是不同的。而据业内人士所说,运用了宽动态摄像机后,就能达到很好的效果,即能同时兼顾到明亮和昏暗的区域,都可以看清。在IP高清时代,宽动态监控是必然趋势。      宽动态摄像机市场现状      随着使用环境的迅速扩大和使用者日益多元化,摄像机的技术和分类也发生了巨大变化。各生产厂商始终致力于提高摄像机的新技术,使其能够最大程度的满足应用要求。其中宽动态摄像机是非常重要的一个分支,在一定程度上也体现了一个摄像机生产厂商的技术发展实力和发展方向。我们知道,摄像机的核心是CCD,目前国内没有CCD的生产能力,主要集中在日本和韩国。由于CCD在生产过程中分不
[安防电子]
如何将ThreadX移植到STM32H7平台
前面我们将ThreadX成功移植到了STM32F4平台,但这只是我们的部分应用。我们希望将ThreadX的优势发挥到我们的更多应用中,所以在这一篇中我们就来实现将ThreadX移植到STM32H7平台中。 1、前期准备   在开始将ThreadX移植到STM32H7平台之前,我们需要做一些软硬件方面的准备。   首先,我们需要准备STM32H7的硬件平台。这次我们采用STM32H750VBT6为控制单元来作为目标平台。这是一款我们在实际项目中使用的,经过验证的,硬件能够稳定运行的平台。   其次,我们需要准备相应的软件资源,也就是ThreadX的源码。ThreadX的源码已经开源到Github上,其地址为: , /
[单片机]
如何将<font color='red'>ThreadX</font>移植到STM32H7平台
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved