事件标志是一个用来实现同步的对象,由多个位组成,用作指示对应事件存在的标志。事件标志由用来指示对应事件存在的位模式(bitpattern)和一个等待事件标志的任务队列组成。

uTenux提供了一组API用于处理事件标志:创建、删除、设置、等待、清除。

1、创建事件标志:tk_cre_flg

为建立的事件标志分配一个控制块

事件结构体:

typedef    struct t_cflg {
VP exinf; /* 事件标志扩展信息 */
ATR flgatr; /* 事件标志的属性 */
UINT iflgptn; /* 事件标志的初始值 */
UB dsname[8]; /* 对象名,没啥用*/
} T_CFLG;

其中事件属性flgatr,可设置为以下的一个或多个值:

TA_TFIFO   任务按FIFO的顺序排队

TA_TPRI     任务按优先级顺序排队

TA_WSGL    不允许等待多个任务(等待一个任务)

TA_WMUL    允许等待多个任务(等待多个任务)

TA_DSNME   设定DS对象名

OS根据事件标志的属性对使用这个事件标志的任务进行调度。

      或等待:等待任意一个条件满足,与等待:等待所有条件满足

我的理解,事件标志就是一个二进制数。因为事件标志本身就是个UINT类型的数字。设置事件标志就是将这个数的某一位置位,清除事件标志就是将这个数的某一位清零。同一个事件标志有多个位,多个任务可以同时使用一个事件标志。

创建事件标志,OS会建立一个事件标志的控制块,用于调度。创建事件标志的时候,会为这个时间标志设置个初始值:iflgtn。与任务和信号量相同,FlgID只是这个事件标志的代表,并不是事件标志的值。

事件标志的属性中如果TA_WMUL设置为1,那么就允许多个任务同时等待一个事件标志。当一个事件标志被设置时,如果多个任务都满足条件,此时这些任务都会被释放。进入等待状态,有系统调度决定哪个先执行哪个后执行。

2、设置和清除时间标志

ER ercd= tk_set_flg(ID flgid,UINT setptn) ;
ER ercd= tk_clr_flg(ID flgid,UINT clrptn);

给出事件标志的ID,和要设置的位,即可设置或清除事件标志。

如果一个调用tk_wai_flg的任务的等待状态释放条件满足,则该任务的等待状态被清除。即此时OS的事件分派器工作了。

3、等待事件标志:

ERercd= tk_wai_flg(ID flgid,UINT waiptn,UINT wfmode,UINT* p_flgptn,TMO tmout);

等待flgid的某些位被置位。如果条件不满足,则进入等待状态。

关于API的详细描述,uTenux内核规范有详细介绍。

【实验描述】

1、创建一个事件标志:FlgID,FlgID事件标志的初始值设置为1. 如果初始值iflgtn被设置为0x02,那么TaskB将先执行一遍循环,然后进入等待后TaskA开始执行。

2、创建两个优先级相同的任务:EventflagSampleTaskA(TaskA)EventflagSampleTaskB(TaskB)

3、创建任务后启动TaskB,在TaskB中启动TaskA。此时由于TaskB的优先权较大,TaskB继续执行,遇到等待事件标志时候停止执行。此时TaskA开始执行。

4、TaskA首先为TaskB设置事件标志(0x02),然后申请事件标志Flag的0x01。条件满足,继续执行清除这个事件标志(0x01)。循环执行,重新等待事件标志,此时事件标志没有被设置,所以TaskA进入休眠状态。TaskB继续执行。

5、TaskB获得优先权开始执行,完成FlagID(0x02)的清除,之后继续等待资格事件。当然,同样没等到进入休眠,任务A继续。

6、如此往复。。。

【实验代码】

#include "EventflagSample.h"

void EventflagSampleTaskA(W stacd,VP exinf);
void EventflagSampleTaskB(W stacd,VP exinf);
void EventflagSamplePutFlg(void);
static ID TaskID_A;
static ID TaskID_B;
static ID FlgID; EXPORT ER EventflagSample( void )
{
T_CTSK ctsk;
T_CFLG cflg; cflg.exinf = (VP) NULL; //没有额外信息
cflg.flgatr = TA_WMUL | TA_TPRI; //事件标志的属性
cflg.iflgptn = 0x01; //事件标志的初始值
FlgID = tk_cre_flg(&cflg);
if(FlgID < E_OK)
{
return FlgID;
}
else
{
tm_putstring((UB*)"成功创建事件标志\n");
} ctsk.bufptr = (VP)NULL;
ctsk.exinf = (VP) NULL;
ctsk.task = EventflagSampleTaskA;
ctsk.stksz = 512;
ctsk.itskpri = 24;
ctsk.tskatr = TA_HLNG | TA_RNG0;
TaskID_A = tk_cre_tsk(&ctsk);
if(TaskID_A < E_OK)
{
return TaskID_A;
}
else
{
tm_putstring("成功创建任务A\n");
} ctsk.task = EventflagSampleTaskB;
ctsk.itskpri = 24;
TaskID_B = tk_cre_tsk(&ctsk);
if(TaskID_B < E_OK)
{
tm_putstring((UB*)"创建任务B出错\n");
return TaskID_B;
}
else
{
tm_putstring("成功创建任务B\n");
}
tm_putstring("启动任务B\n");
tk_sta_tsk(TaskID_B,5); return E_OK;
} void EventflagSampleTaskA(W stacd,VP exinf)
{
UINT flgptn;
while(1)
{
tm_putstring((UB*)"任务A循环开始\n");
tk_set_flg(FlgID,0x02); //为任务B设置事件标志
tk_wai_flg(FlgID,0x01,TWF_ANDW,&flgptn,-1);
EventflagSamplePutFlg();
tm_putstring((UB*)"\n");
tk_clr_flg(FlgID,0x01); //清除任务A自己的事件标志 EventflagSamplePutFlg(); //输出任务信息:3:两个事件标志都被设置,2:任务B事件标志被设置,1:任务A事件标志被设置
tm_putstring((UB*)"TaskAEnd\n");
}
} void EventflagSampleTaskB(W stacd,VP exinf)
{
UINT flgptn;
tm_putstring((UB*)"任务B启动任务A\n");
tk_sta_tsk(TaskID_A,0);
while(1)
{
tm_putstring((UB*)"任务B循环开始\n");
tk_set_flg(FlgID,0x01); //为任务A设置事件标志
tk_wai_flg(FlgID,0x02,TWF_ANDW,&flgptn,-1);
EventflagSamplePutFlg();
tm_putstring((UB*)"\n"); tk_clr_flg(FlgID,0x02); //清除自己的事件标志
EventflagSamplePutFlg();
tm_putstring((UB*)"TaskBEnd\n"); }
while(1);
} void EventflagSamplePutFlg(void)
{
B flgptn[10];
T_RFLG rflg; tm_putstring((UB*)"Now Flag pattern is 0x0000000");
tk_ref_flg(FlgID, &rflg);
ltostr(rflg.flgptn,flgptn,16,10);
tm_putstring((UB*)flgptn);
tm_putstring((UB*)"\n");
}

【实验输出】

----------------------------------------------------
        micro Tenux Version 1.6.00(build 0180)     
            Supported MCU is ST STM32F407VG        
  Copyright(c) 2008-2013 by Dalian uLoong Co.,Ltd. 
----------------------------------------------------

成功创建事件标志
成功创建任务A
成功创建任务B
启动任务B
任务B启动任务A
任务B循环开始
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001
TaskAEnd
任务A循环开始
Now Flag pattern is 0x00000003

Now Flag pattern is 0x00000001

........................

【总结】

事件标志应该是为了等待两个任务同步而设立的。每个任务完成一定的工作之后,通过事件标志通知另一个任务可以执行了。从而使得两个任务之间协调完成一项工作。

【uTenux实验】事件标志的更多相关文章

  1. 16.3-uC/OS-III同步 (事件标志组实验)

    事件标志组,顾名思义,就是若干个事件标志的组合,代表若干个事件是否发生,通常用于集合两个或两个以上事件的状态 . 1.如果想要使用事件标志组,就必须事先使能事件标志组.消息队列的使能位于“os_cfg ...

  2. FreeRTOS 事件标志组 ——提高篇

    假设你已经看过FreeRTOS 事件标志组这篇随笔了. 之前的基础篇,真的就只是简单了解一下,相当于大学实验室的实验,但是,我们实际公司项目中,需要更多地思考,就算我们之前只是学习了基础概念以及基础语 ...

  3. FreeRTOS 事件标志组

    以下转载自安富莱电子: http://forum.armfly.com/forum.php 为什么要使用事件标志事件标志组是实现多任务同步的有效机制之一.也许有不理解的初学者会问采用事件标志组多麻烦, ...

  4. FreeRTOS 任务计数信号量,任务二值信号量,任务事件标志组,任务消息邮箱

    以下基础内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 计数信号量的另一种实现方式----基于任务通知(Task Not ...

  5. FreeRTOS_事件标志组

    FreeRTOS事件标志组 事件标志组简介 1. 事件位(事件标志) 事件位用于表明某个事件是否发生,事件位通常用作事件标志,比如下面的几个例子: 当收到一条消息并且把这条消息处理掉以后就可以将某个位 ...

  6. FreeRTOS 任务通知模拟事件标志组

    实验 //设置事件位的任务 void eventsetbit_task(void *pvParameters) { u8 key; while(1) { if(EventGroupTask_Handl ...

  7. UCOSIII事件标志组

    两种同步机制 "或"同步 "与"同步 使能 #define OS_CFG_FLAG_EN 1u /* Enable (1) or Disable (0) cod ...

  8. ucos中信号量 事件标志 消息队列都怎么用

    信号量 事件标志和消息队列分别应用于什么场景(反正我学的时候有点闹不清,现在总结一下): 信号量和事件标志用于任务同步.详细来说,这个功能可以替代以前裸机中你打一个标记的功能,比如使用了一个定时器,5 ...

  9. 16.2-uC/OS-III同步 (事件标志组)

    事件标志组 1.当任务要与多个事件同步时可以使用事件标志.若其中的任意一个事件发生时任务被就绪, 叫做逻辑或(OR).若所有的事件都发生时任务被就绪,叫做逻辑与( AND). 2.用户可以创建任意个事 ...

随机推荐

  1. POJ----(3974 )Palindrome [最长回文串]

    Time Limit: 15000MS   Memory Limit: 65536K Total Submissions: 5121   Accepted: 1834 Description Andy ...

  2. 在内部架设NuGet服务器(转载)

    合肥程序员群:49313181.    合肥实名程序员群:128131462 (不愿透露姓名和信息者勿加入)Q  Q:408365330     E-Mail:egojit@qq.com 在公司内部有 ...

  3. 三种JS方法确定元素在数组中的索引值

    第一种:数组遍历 function search(arr,dst){ var i = arr.length; while(i-=1){ if (arr[i] == dst){ return i; } ...

  4. SqlParameter设定value为0却变成null

    直接MSDN:http://msdn.microsoft.com/zh-cn/library/0881fz2y(VS.80).aspx 当在 value 参数中指定 Object 时,SqlDbTyp ...

  5. html5的spellcheck属性(拼写、文法检查)

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  6. HttpCache ETag与Last-Modified与Expires

    Last-Modified 是检查一个资源最后修改时间.如果时间过期了则返回资源内容.如果没过期,返回304.当Last-Modified更新了,但是资源本质上没有更新,比如资源是A,Last-Mod ...

  7. WCF初探-14:WCF服务协定

    前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多 ...

  8. CSS 高级技巧汇总

    在我们平时写代码的时候没有没有掌握一些CSS技巧呢? 今天给大家分享一个<CSS 高级技巧汇总让你的代码简洁高效>.大家务必掌握这些小技巧,会让你非常高效率的写出网页的. ◆使用 :not ...

  9. iOS开发UI篇—实现UItableview控件数据刷新

    iOS开发UI篇—实现UItableview控件数据刷新 一.项目文件结构和plist文件 二.实现效果 1.说明:这是一个英雄展示界面,点击选中行,可以修改改行英雄的名称(完成数据刷新的操作). 运 ...

  10. 关于VS中文件属性的解释

    生成操作(BuildAction) 属性:BuildAction 属性指示 Visual Studio .NET 在执行生成时对文件执行的操作.BuildAction 可以具有以下几个值之一: 无(N ...