【FreeRTOS】事件标志与任务通知

目录

一、事件标志组

1、创建事件标志组

(1)动态方法

(2)静态方法

2、设置标志位

(1)清零操作

(2)置位操作

3、获取事件标志组值

(1)任务级

(2)中断级

4、等待指定的事件位

二、任务通知

1、发送通知函数

(1)函数xTaskNotify()

(2)函数xTaskNotifyFromISR()

(3)函数xTaskNotifyGive()

(4)函数vTaskNotifyGiveFromISR()

(5)函数xTaskNotifyAndQuery()

(6)函数xTaskNotifyAndQueryFromISR()

2、获取任务通知函数

(1)函数ulTaskNotifyTake()

(2)函数xTaskNotifyWait()


一、事件标志组

       事件是一种实现任务通信的机制,主要用于实现多任务间通信,这与信号量类似,与信号量不同的是事件可以实现一对多,多对多同步,即一个任务可以等待多个事件发生后再执行,也可以是其中任一个事件发生就执行

       一个事件组由多个事件位组成,一个事件位就是一个二进制位,当某个事件发生就将对应事件位置1,表明这个事件已经发生了。

       事件标志组的数据类型为EventGroupHandle_t(事件标志组句柄类型),是一个结构体指针变量,在"event_groups.h"文件有定义如下:

struct EventGroupDef_t;
typedef struct EventGroupDef_t   * EventGroupHandle_t; //控制块句柄(指针)


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

    #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;

事件标志组所存储的事件位个数有关的宏定义"FreeRTOSConfig.h"文件中:

#define configUSE_16_BIT_TICKS              0

当为1时,为16位

当为0时,为32位(STM32为32位的所以为0)

分别对应可存储的事件位个数为8个和24个,其中高8位用作其他不可用。

1、创建事件标志组

(1)动态方法

/*函数原型*/
EventGroupHandle_t xEventGroupCreate( void );

/*
*参数:  无;
*返回值:创建失败NULL,创建成功返回事件标志组句柄;
*/

(2)静态方法

/*函数原型*/
EventGroupHandle_t xEventGroupCreateStatic( StaticEventGroup_t * pxEventGroupBuffer );

/*
*参数:
* pxEventGroupBuffer:指向StaticEventGroup_t类型的变量,用于保存事件标志组结构体;
*返回值:              创建失败NULL,创建成功返回事件标志组句柄;
*/

2、设置标志位

(1)清零操作

任务级:

/*函数原型*/
EventBits_t xEventGroupClearBits( EventGroupHandle_t xEventGroup,
                                  const EventBits_t uxBitsToClear )

/*
*参数:
* xEventGroup:  事件标志组句柄;
* uxBitsToClear:要清零的事件位,清除bit3(0000 1000),则为0x08;清除bit2和bit3(0000 1100);则        
                 为0x0c。
*返回值:         清零前的事件组值;
*/

中断级

/*函数原型*/
BaseType_t xEventGroupClearBitsFromISR( EventGroupHandle_t xEventGroup,
                                        const EventBits_t uxBitsToClear )
/*
*参数:
* xEventGroup:  事件标志组句柄;
* uxBitsToClear:要清零的事件位,清除bit3(0000 1000),则为0x08;清除bit2和bit3(0000 1100);则为     
                 0x0c。
*返回值:
*pdPASS:        事件位清零成功;
*pdPALSE:       事件位清零失败;
*/

/*此处为条件编译,使用需要将以下宏定义为1*/
#if ( ( configUSE_TRACE_FACILITY == 1 ) && ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 1 ) )

(2)置位操作

任务级

/*函数原型*/
EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
                                const EventBits_t uxBitsToSet )

/*
*参数:
* xEventGroup: 事件标志组句柄;
* uxBitsToSet :要置1的事件位,置位bit3(0000 1000),则为0x08;置位bit2和bit3(0000 1100);则为 
                0x0c。
*返回值:        置1后的事件组值;
*/

中断级

/*函数原型*/
BaseType_t xEventGroupSetBitsFromISR( EventGroupHandle_t xEventGroup,
                                      const EventBits_t uxBitsToSet,
                                      BaseType_t * pxHigherPriorityTaskWoken )

/*
*参数:
* xEventGroup: 事件标志组句柄;
* uxBitsToSet :要置1的事件位,置位bit3(0000 1000),则为0x08;置位bit2和bit3(0000 1100);则为     
                 0x0c。
*pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换,只需提供变量来保存即可,当该值为 
                            pdTRUE时退出前需要进行一次任务切换。
*返回值:
*pdPASS: 事件位置1成功
*pdPALSE:事件位置1失败
*/

3、获取事件标志组值

(1)任务级

/*函数原型*/
EventBits_t xEventGroupGetBits( EventGroupHandle_t xEventGroup )

/*参数
*xEventGroup:事件标志组句柄;
*返回值:      事件组值(不执行清零操作);
*/

/*此函数为一个宏,调用的时清零函数*/
#define xEventGroupGetBits( xEventGroup )    xEventGroupClearBits( xEventGroup, 0 )

(2)中断级

/*函数原型*/
EventBits_t xEventGroupGetBitsFromISR( EventGroupHandle_t xEventGroup )

/*参数
*xEventGroup:事件标志组句柄;
*返回值:      事件组值;
*/

/*操作时读取事件标志组结构体中的uxEventBits */
uxReturn = pxEventBits->uxEventBits;

4、等待指定的事件位

/*函数原型*/
EventBits_t xEventGroupWaitBits( EventGroupHandle_t xEventGroup,
                                 const EventBits_t uxBitsToWaitFor,
                                 const BaseType_t xClearOnExit,
                                 const BaseType_t xWaitForAllBits,
                                 TickType_t xTicksToWait )

/*参数
*xEventGroup:      事件标志组句柄;
* uxBitsToWaitFor: 等待的指定位,要置1的事件位,等待位bit3(0000 1000),则为0x08;等待位bit2和 
                    bit3(0000 1100);则为0x0c;

* xClearOnExit:    退出后是否将等到的事件位清零,pdTRUE清零,pdFALSE不清零;
* xWaitForAllBits: 是否等待所有位,pdTRUE等待所有指定位满足(置1)才返回,pdFALSE等待指定位中任一     
                    位满足(置1)就返回;
* xTicksToWait:    等待阻塞时间;
*返回值:
*       返回所等指定位满足(置1)后的事件标志组值,如果因为阻塞时间到则返回值无意义;
*/

二、任务通知

       任务通知也是一种信号量(事件),不需要创建,它是存在于任务控制块的一个32位的(数组)变量ulNotifiedValue:

#if ( configUSE_TASK_NOTIFICATIONS == 1 )
   volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];//任务通知组值
   volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];//任务通知状态
#endif

        大多数情况下,任务通知可以替代二值信号量、计数信号量、事件组,也可以替代长度为1的队列(可以保存一个32位的整数或指针值)。使用任务通知相较于其他信号量可以提高效率

发送通知给任务的几种方式:

(1)直接覆盖通知值

(1)如果有未处理通知,不覆盖通知值

(3)设置通知值的一个或多个位,当事件组使用

(4)增加通知值,当计数型信号量使用

任务通知的限制:

(1)只能有一个任务接收通知消息,信号量可以由多个任务接收;

(2)只有等待通知的任务可以被阻塞,发送通知的任务不会进入阻塞态。

相关函数及定义在"tasks.c"和"task.h"文件中。

1、发送通知函数

以上任务都是宏定义的,调用的函数为以下两个函数:

/*任务级*/
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,    //任务句柄
                               UBaseType_t uxIndexToNotify,   //通知值
                               uint32_t ulValue,
                               eNotifyAction eAction,         //发送通知方式
                               uint32_t * pulPreviousNotificationValue )


/*中断级*/
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
                                      UBaseType_t uxIndexToNotify,
                                      uint32_t ulValue,
                                      eNotifyAction eAction,
                                      uint32_t * pulPreviousNotificationValue,
                                      BaseType_t * pxHigherPriorityTaskWoken )

/*更新方法的枚举值列表*/
typedef enum
{
    eNoAction = 0,                /* 通知但不更新值 */
    eSetBits,                     /* 更新指定位*/
    eIncrement,                   /* 通知值加1*/
    eSetValueWithOverwrite,       /* 覆写通知值*/
    eSetValueWithoutOverwrite     /* 不覆写通知值*/
} eNotifyAction;

(1)函数xTaskNotify()

/*函数原型*/
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify,
                        uint32_t ulValue,
                        eNotifyAction eAction )

/*
*参数:
* xTaskToNotify:任务句柄,要发向的任务;
* ulValue:      任务通知值;
*/eAction:      任务通知更新方法;
*返回值:
* pdPASS:    成功;
* pdFAIL:    失败;
*/



/*函数宏定义*/
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \
    xTaskGenericNotify( ( xTaskToNotify ), 
                        ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                        ( ulValue ),
                        ( eAction ), 
                          NULL )

(2)函数xTaskNotifyFromISR()

/*函数原型*/
BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify,
                               uint32_t ulValue,
                               eNotifyAction eAction,
                               BaseType_t *pxHigherPriorityTaskWoken );

/*
*参数:
* xTaskToNotify:    任务句柄,要发向的任务;
* ulValue:          任务通知值;
*/eAction:          任务通知更新方法;
* pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换,只需提供变量来保存即可,当该值为 
                             pdTRUE时退出前需要进行一次任务切换。
*返回值:
* pdPASS:成功;
* pdFAIL:失败;
*/

/*函数宏定义*/
#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \
 xTaskGenericNotifyFromISR( ( xTaskToNotify ), 
                            ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                            ( ulValue ), 
                            ( eAction ),
                              NULL, 
                            ( pxHigherPriorityTaskWoken ) )

(3)函数xTaskNotifyGive()

           该函数将任务通知值加1。(任务级)

/*函数原型*/
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );

/*
*参数:
* xTaskToNotify: 任务句柄,要发向的任务;
*返回值:
* pdPASS:        此函数只返回该值;
*/

/*函数宏定义*/
#define xTaskNotifyGive( xTaskToNotify ) \
    xTaskGenericNotify( ( xTaskToNotify ), 
                        ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                        ( 0 ),
                          eIncrement, 
                          NULL )

(4)函数vTaskNotifyGiveFromISR()

        该函数将任务通知值加1。(中断级)        

/*函数原型*/
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle,
                             BaseType_t *pxHigherPriorityTaskWoken );

/*
*参数:
* xTaskHandle: 任务句柄,要发向的任务;
* pxHigherPriorityTaskWoken:标记退出此函数后是否进行任务切换,只需提供变量来保存即可,当该值为 
                             pdTRUE时退出前需要进行一次任务切换。
*返回值:        无;
*/

/*函数宏定义*/
#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \
        vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), 
                                       ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                                       ( pxHigherPriorityTaskWoken ) );

(5)函数xTaskNotifyAndQuery()

此函数与xTaskNotify()类似,仅多一个参数用于保存更新前的通知值。

/*函数原型*/
BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify,
                                uint32_t ulValue,
                                eNotifyAction eAction,
                                uint32_t *pulPreviousNotifyValue );

/*
*参数:
* xTaskToNotify:         任务句柄,要发向的任务;
* ulValue:               任务通知值;
*/eAction:               任务通知更新方法;
* pulPreviousNotifyValue:保存更新前的任务通知值;
*返回值:
* pdPASS:    成功;
* pdFAIL:    失败;
*/

/*函数宏定义*/
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \
        xTaskGenericNotify( ( xTaskToNotify ), 
                            ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                            ( ulValue ), 
                            ( eAction ), 
                            ( pulPreviousNotifyValue ) )

(6)函数xTaskNotifyAndQueryFromISR()

xTaskNotifyAndQuery()的中断版本(中断服务函数中使用)。

/*函数原型*/
BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify,
                                       uint32_t ulValue,
                                       eNotifyAction eAction,
                                       uint32_t *pulPreviousNotificationValue,
                                       BaseType_t *pxHigherPriorityTaskWoken );
/*
*参数:
* xTaskToNotify:              任务句柄,要发向的任务;
* ulValue:                    任务通知值;
*/eAction:                    任务通知更新方法;
* pulPreviousNotifyValue:     保存更新前的任务通知值;
* pxHigherPriorityTaskWoken:  标记退出此函数后是否进行任务切换,只需提供变量来保存即可,当该值 
                               为pdTRUE时退出前需要进行一次任务切换。
*返回值:
* pdPASS:    成功;
* pdFAIL:    失败;
*/

/*函数宏定义*/
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, 
                                    ulValue, 
                                    eAction,    
                                    pulPreviousNotificationValue, 
                                    pxHigherPriorityTaskWoken ) \

        xTaskGenericNotifyFromISR( ( xTaskToNotify ), 
                                   ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                                   ( ulValue ), 
                                   ( eAction ), 
                                   ( pulPreviousNotificationValue ), 
                                   ( pxHigherPriorityTaskWoken ) )

2、获取任务通知函数

(1)函数ulTaskNotifyTake()

/*函数原型*/
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait )

/*
*参数:
* xClearCountOnExit:           pdFALSE时,退出前将任务通知值减1(计数型信号量),pdTRUE时,退         
*                               出前将任务通知值清零(二值信号量);
* xTicksToWait:xTicksToWait:   阻塞时间,无通知时的等待时间;
*
*返回值:                        返回减1或清零前的通知值;
*/

/*函数宏定义*/
#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \
        ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), 
                                 ( xClearCountOnExit ),
                                 ( xTicksToWait ) )

(2)函数xTaskNotifyWait()

/*函数原型*/
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
                            uint32_t ulBitsToClearOnExit,
                            uint32_t *pulNotificationValue,
                            TickType_t xTicksToWait );
/*
*参数:
* ulBitsToClearOnEntry:   使用通知之前将哪些位清零(可用于屏蔽某些位吧);
* ulBitsToClearOnExit:    退出前将哪些位清零;
* pulNotificationValue:   用于保存接收到的任务通知值;
* xTicksToWait:           阻塞时间,无通知时的等待时间;
*返回值:
*pdTRUE:     成功;
*pdFALSE:    失败;
*/

/*在新版源码中函数是一个宏*/
#define xTaskNotifyWait( ulBitsToClearOnEntry, 
                         ulBitsToClearOnExit,
                         pulNotificationValue,
                         xTicksToWait ) \

        xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, 
                              ( ulBitsToClearOnEntry ), 
                              ( ulBitsToClearOnExit ), 
                              ( pulNotificationValue ), 
                              ( xTicksToWait ) )

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值