IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> FreeRTOS学习七(事件标志组) -> 正文阅读

[C++知识库]FreeRTOS学习七(事件标志组)

????????RTOS中可以通过信号量来完成同步,但是信号量只能与单个的事件或任务进行同步。有时某个任务可能会需要与多个事件或任务进行同步,此时信号量就无法满足要求了。事件标志组就排上了用场。

事件位(事件标志)

????????事件位用来表明某个事件是否发生,事件位通常用于事件标志。比如有个事件需要处理,则将某个标志位置1。没有事件要处理,则置0.

事件组

????????一个事件组就是一组的事件位,事件组中的事件位通过位编号来访问。比如事件标志组的Bit0表示任务0需要处理,bit1表示任务1需要处理,bit2表示任务2需要处理。

????????事件标志组的事件标志位类型为EventBits。

typedef TickType_t EventBits_t;

#if( configUSE_16_BIT_TICKS == 1 )
typedef uint16_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffff
#else

typedef uint32_t TickType_t;
#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
/* 32-bit tick type on a 32-bit architecture, so reads of the tick count do
not need to be guarded with a critical section. */
#define portTICK_TYPE_IS_ATOMIC 1
#endif

????????可以看到EventBits的类型是TickType,而TickType的类型根据configUSE_16_BIT_TICKS标志来,该标志位1时,TickType类型为uint16_t 。该标志位0时,TickType类型为uint32_t。EventBits的变量可以存储24个事件位另外高8位有其他用。事件位0存放在变量的bit0上,变量的Bit1就是事件位1,以此类推。

1.xEventGroupCreate()创建事件标志组(动态内存)

此函数用于创建一个事件标志组,所需要的内存通过动态内存管理方法分配。

函数原型:

EventGroupHandle_t xEventGroupCreate( void )

参数:无

返回值:

NULL:创建失败

其他值:创建成功的事件标志组句柄

实例:

EventGroupHandle_t xCreatedEventGroup;

xCreatedEventGroup = xEventGroupCreate();

2.xEventGroupCreateStatic() 创建事件标志组(静态内存)

函数原型:

EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t *pxEventGroupBuffer ) 

参数:

pxEventGroupBuffer :参数指向一个StaticEventGroup_t类型的变量,用来保存事件标志组结构体

返回值:

NULL:失败

其他值:成功的时间标志组句柄

实例:

StaticEventGroup_t xEventGroupBuffer;xEventGroup = xEventGroupCreateStatic( &xEventGroupBuffer );

3.xEventGroupSetBits()将指定事件位置1

函数原型:

EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet ) PRIVILEGED_FUNCTION;

参数:

xEventGroup:要操作的事件标志组

uxBitsToSet :指定要置1的事件位,比如要将Bit3置1的话,就设置为0x08。可以同时将多个bit置1.

返回值:

任何值:在将指定事件置1后的事件组值

实例:

EventBits_t uxBits;

uxBits = xEventGroupSetBits(

    xEventGroup, // The event group being updated.

    BIT_0 | BIT_4 );// The bits being set.

4.xEventGroupSetBitsFromISR()中断中将指定事件位置1

函数原型:

BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;

参数:

xEventGroup:要操作的事件标志组

uxBitsToSet :指定要置1的事件位,比如要将Bit3置1的话,就设置为0x08。可以同时将多个bit置1.

pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换。当设置为pdTRUE时,退出中断服务函数之前一定会进行一次任务切换。

返回值:

pdPASS:成功

pdFALSE:失败

实例:

xHigherPriorityTaskWoken = pdFALSE;

xResult = xEventGroupSetBitsFromISR(

    xEventGroup, // The event group being updated.

    BIT_0 | BIT_4   // The bits being set.

    &xHigherPriorityTaskWoken );

5.xEventGroupClearBits()清除指定事件位

函数原型:

EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;

参数:

xEventGroup:要操作的时间标志组的句柄

uxBitsToClear :要清零的事件位。可以同时清除多个Bit

返回值:

任何值:将指定事件位清零之前的事件组值

实例:

EventBits_t uxBits;

uxBits = xEventGroupClearBits(

    xEventGroup, // The event group being updated.

    BIT_0 | BIT_4 );// The bits being cleared.

6.xEventGroupClearBitsFromISR()中断中清除指定事件位

函数原型:

BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToClear ) PRIVILEGED_FUNCTION;

参数:

xEventGroup:要操作的时间标志组的句柄

uxBitsToClear :要清零的事件位。可以同时清除多个Bit

返回值:

pdPASS:成功

pdFAIL:失败

实例:

xResult = xEventGroupClearBitsFromISR(

xEventGroup,  // The event group being updated.

BIT_0 | BIT_4 ); // The bits being set.

7.xEventGroupGetBits()获取当前事件标志组值

函数原型:

#define xEventGroupGetBits( xEventGroup ) xEventGroupClearBits( xEventGroup, 0 )

参数:

xEventGroup :要获取的事件标志组的句柄

返回值:

当前标志组的值

实例:

EventBits_t xResult

xResult  = xEventGroupGetBits(xEventGroup)

8.xEventGroupGetBitsFromISR()中断中获取当前事件标志组值

函数原型:

EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup ) PRIVILEGED_FUNCTION;

参数:

xEventGroup :要获取的事件标志组的句柄

返回值:

当前标志组的值

实例:

EventBits_t xResult

xResult  = xEventGroupGetBitsFromISR(xEventGroup)

9.xEventGroupWaitBits()等待时间标志位

????????某个任务可能需要与多个事件进行同步,那么这个任务就需要等待并判断多个事件位(标志)。调用该函数后如果任务要等待的事件位还没有准备好(置1或清零)的话,任务就会进入阻塞状态,直到阻塞时间到达或者所等待的时间位准备好

函数原型:

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

参数:

xEventGroup:指定要等待的事件标志组

uxBitsToWaitFor:指定要等待的事件位。比如要等待bit0和(或)bit1,此参数为0x03

xClearOnExit:在退出此函数之前由参数uxBitsToWaitFor所设置的这些事件位是否清零。pdTRUE清零。pdFALSE不清零。

xWaitForAllBits:此参数为pdTRUE时,当uxBitsToWaitFor所设置的这些事件位都置1,或者指定的阻塞时间到的时候,才会返回。当为pdFALSE,只要uxBitsToWaitFor所设置的这些事件位其中的任意一个置1,或者指定的阻塞时间到,才返回。

xTicksToWait:设置阻塞时间

返回值:

????????返回当所等待的事件位置1以后的时间标志组的值,或阻塞时间到。根据这个值就知道哪些时间位置1了。如果函数因为阻塞时间到而返回的话,该返回值不代表任何含义。

实例:

EventBits_t uxBits;
uxBits = xEventGroupWaitBits(
    xEventGroup, // The event group being tested.
    BIT_0 | BIT_4, // The bits within the event group to wait for.
    pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
    pdFALSE, // Don't wait for both bits, either bit will do.
    xTicksToWait ); // Wait a maximum of 100ms for either bit to be set.

if( ( uxBits & ( BIT_0 | BIT_4 ) ) == ( BIT_0 | BIT_4 ) )
{
// bit0和bit4都被检测到
}
else if( ( uxBits & BIT_0 ) != 0 )
{
// bit0被检测到
}
else if( ( uxBits & BIT_4 ) != 0 )
{
// bit4被检测到
}
else
{
// 超时
}

代码验证:

????????创建3个任务,任务1创建一个1秒的周期定时器,在定时器回调中设置标志位bit0。任务2以1.5秒周期置标志位Bit1。任务3以1秒周期置标志位Bit2。任务1中等待标志位。等待到之后自动清除标志位。

任务1

#define BIT_0 ( 1 << 0 )
#define BIT_1 ( 1 << 1 )
#define BIT_2 ( 1 << 2 )
#define BIT_3 ( 1 << 3 )

EventGroupHandle_t xCreatedEventGroup;
void vTimerCallback( TimerHandle_t pxTimer )
{
    configASSERT( pxTimer );
    static uint32_t time_cnt = 0;
    time_cnt++;
    int32_t lArrayIndex = 0;
    lArrayIndex = ( int32_t ) pvTimerGetTimerID( pxTimer );
    LOG_I(common,"[DEBUG]:timer name:%stimer id:%d",pcTimerGetName(pxTimer),lArrayIndex);
    if(lArrayIndex = timer_id)
    {
        LOG_I(common,"[DEBUG]:time cnt:%d",time_cnt);
        LOG_I(common,"[TIMER]:BIT0 set");
        xEventGroupSetBits(xCreatedEventGroup,BIT_0);
    }
}

static void vTestTask1_H(void *pvParameters)
{
    xCreatedEventGroup = xEventGroupCreate();   //创建事件组
    xTimer_test = xTimerCreate("Test timer",       /* Just a text name, not used by the kernel. */
                                    (1000 / portTICK_PERIOD_MS),    /* The timer period in ticks. */
                                     pdTRUE,        /* The timers will auto-reload themselves when they expire. */
                                     (void *)timer_id,   /* Assign each timer a unique id equal to its array index. */
                                     vTimerCallback /* Each timer calls the same callback when it expires. */
                                    );
    if(xTimer_test == NULL)   
    {
        LOG_I(common,"[TASK1]:Timer create fail");  //失败
    }
    else
    {
        LOG_I(common,"[TASK1]:Timer create sucess");  //成功
        if( xTimerStart( xTimer_test, 0 ) != pdPASS )
        {
          LOG_I(common,"[TASK1]:Timer start fail");  //失败
        }
    }
    EventBits_t uxBits;
    while(1)
    {
        LOG_I(common,"[TASK1]:wait event group");
        uxBits = xEventGroupWaitBits(
                xCreatedEventGroup, // The event group being tested.
                BIT_0 | BIT_1 | BIT_2 | BIT_3, // The bits within the event group to wait for.
                pdTRUE, // BIT_0 and BIT_4 should be cleared before returning.
                pdFALSE, // Don't wait for both bits, either bit will do.
                portMAX_DELAY ); // Wait a maximum of 100ms for either bit to be set.

        LOG_I(common,"[DEBUG]:event group,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        if(uxBits & BIT_0)
        {
            LOG_I(common,"[DEBUG]:event group BIT0 get");
        }
        if(uxBits & BIT_1)
        {
            LOG_I(common,"[DEBUG]:event group BIT1 get");
        }
        if(uxBits & BIT_2)
        {
            LOG_I(common,"[DEBUG]:event group BIT2 get");
        }
        if(uxBits & BIT_3)
        {
            LOG_I(common,"[DEBUG]:event group BIT3 get");
        }
}

任务2

static void vTestTask2_M(void *pvParameters)
{
    while(1)
    {
        LOG_I(common,"[TASK2]:BIT1 set");
        xEventGroupSetBits(xCreatedEventGroup,BIT_1);
        vTaskDelay(1500);
    }
}

任务3

static void vTestTask3_L(void *pvParameters)
{
    while(1)
    {
        LOG_I(common,"[TASK3]:BIT2 set");
        xEventGroupSetBits(xCreatedEventGroup,BIT_2);
         vTaskDelay(500);
    }
}

结果:

结果分析:

  1. 等待事件组
  2. Bit1置位
  3. 事件组BIT1被检测到。当前事件组为0
  4. 等待事件组
  5. Bit2置位
  6. 事件组BIT2被检测到。当前事件组为0
  7. Bit0置位
  8. 事件组BIT0检测到。当前事件组为0

????????从结果可以看到,因为等待事件组的函数设置了返回后清除标志位,所以每次在检测到事件组之后获取事件组,结果都是0.

将等待事件组参数设置为不清除,然后手动清除

LOG_I(common,"[TASK1]:wait event group");

        uxBits = xEventGroupWaitBits(
                    xCreatedEventGroup, // The event group being tested
                    BIT_0 | BIT_1 | BIT_2 | BIT_3, // The bits within the event group to wait for.
                    pdFALSE, // BIT_0 and BIT_4 should be cleared before returning.
                    pdFALSE, // Don't wait for both bits, either bit will do
                    portMAX_DELAY ); // Wait a maximum of 100ms for either bit to be set.
        LOG_I(common,"[DEBUG]:event                             group,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        if(uxBits & BIT_0)
        {
            LOG_I(common,"[DEBUG]:event group BIT0 get");
            xEventGroupClearBits(xCreatedEventGroup,BIT_0);
            LOG_I(common,"[DEBUG]:event group BIT0         clean,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        }
        if(uxBits & BIT_1)
        {
            LOG_I(common,"[DEBUG]:event group BIT1 get");
            xEventGroupClearBits(xCreatedEventGroup,BIT_1);
            LOG_I(common,"[DEBUG]:event group BIT1 clean,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        }
        if(uxBits & BIT_2)
        {
            LOG_I(common,"[DEBUG]:event group BIT2 get");
            xEventGroupClearBits(xCreatedEventGroup,BIT_2);
            LOG_I(common,"[DEBUG]:event group BIT2 clean,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        }
        if(uxBits & BIT_3)
        {
            LOG_I(common,"[DEBUG]:event group BIT3 get");
            xEventGroupClearBits(xCreatedEventGroup,BIT_3);
            LOG_I(common,"[DEBUG]:event group BIT3 clean,rst:%d",xEventGroupGetBits(xCreatedEventGroup));
        }

}

结果:

结果分析:

  1. 等待事件组
  2. BIT1被置位
  3. 事件组被检测到,此时事件组值为0x02.
  4. 检测是到BIT1
  5. 清零事件组值
  6. 重新等待

????????从结果可以看,如果等待事件组的函数被设置为不清除,那就需要用户手动调用函数去清除事件组。

?

?

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-04-04 11:50:13  更:2022-04-04 11:56:29 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 23:42:58-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码