【uTenux实验】事件标志
事件标志是一个用来实现同步的对象,由多个位组成,用作指示对应事件存在的标志。事件标志由用来指示对应事件存在的位模式(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实验】事件标志的更多相关文章
- 16.3-uC/OS-III同步 (事件标志组实验)
事件标志组,顾名思义,就是若干个事件标志的组合,代表若干个事件是否发生,通常用于集合两个或两个以上事件的状态 . 1.如果想要使用事件标志组,就必须事先使能事件标志组.消息队列的使能位于“os_cfg ...
- FreeRTOS 事件标志组 ——提高篇
假设你已经看过FreeRTOS 事件标志组这篇随笔了. 之前的基础篇,真的就只是简单了解一下,相当于大学实验室的实验,但是,我们实际公司项目中,需要更多地思考,就算我们之前只是学习了基础概念以及基础语 ...
- FreeRTOS 事件标志组
以下转载自安富莱电子: http://forum.armfly.com/forum.php 为什么要使用事件标志事件标志组是实现多任务同步的有效机制之一.也许有不理解的初学者会问采用事件标志组多麻烦, ...
- FreeRTOS 任务计数信号量,任务二值信号量,任务事件标志组,任务消息邮箱
以下基础内容转载自安富莱电子: http://forum.armfly.com/forum.php 本章节为大家讲解 FreeRTOS 计数信号量的另一种实现方式----基于任务通知(Task Not ...
- FreeRTOS_事件标志组
FreeRTOS事件标志组 事件标志组简介 1. 事件位(事件标志) 事件位用于表明某个事件是否发生,事件位通常用作事件标志,比如下面的几个例子: 当收到一条消息并且把这条消息处理掉以后就可以将某个位 ...
- FreeRTOS 任务通知模拟事件标志组
实验 //设置事件位的任务 void eventsetbit_task(void *pvParameters) { u8 key; while(1) { if(EventGroupTask_Handl ...
- UCOSIII事件标志组
两种同步机制 "或"同步 "与"同步 使能 #define OS_CFG_FLAG_EN 1u /* Enable (1) or Disable (0) cod ...
- ucos中信号量 事件标志 消息队列都怎么用
信号量 事件标志和消息队列分别应用于什么场景(反正我学的时候有点闹不清,现在总结一下): 信号量和事件标志用于任务同步.详细来说,这个功能可以替代以前裸机中你打一个标记的功能,比如使用了一个定时器,5 ...
- 16.2-uC/OS-III同步 (事件标志组)
事件标志组 1.当任务要与多个事件同步时可以使用事件标志.若其中的任意一个事件发生时任务被就绪, 叫做逻辑或(OR).若所有的事件都发生时任务被就绪,叫做逻辑与( AND). 2.用户可以创建任意个事 ...
随机推荐
- 转linq中的Single()、First()、Take(1) LINQ 标准的查询操作符 排序 orderby、thenby、Take
Single():操作一个集合,同时强要求只有一个对象匹配,并返回这一个. First():操作一个集合,可以有多个对象匹配,但是只返回第一个. Take(1):操作一个集合,可以有对个对象匹配,单只 ...
- table表格中实现tbody部分可滚动,且thead部分固定
1.想要实现表格的thead部分固定切tbody部分可滚动,就需要将thead与tbody进行分离,具体做法是 1.设置thead,tbody都为display:block: 2.设置th与td的宽度 ...
- C#泛型List的用法
C#泛型List的用法 来源:C#学习 发布时间:2014/1/4 一.List<T>命名空间: System.Collections.Generic(程序集:mscorlib) 二 ...
- MONGODB 与sql聚合操作对应图
MongoDB 高级查询条件操作符 2012-04-25 15:35:19| 分类: MongoDB | 标签:mongodb使用 mongodb查询 |举报|字号 订阅 http://blo ...
- RichTextBox文字处理控件属性介绍
RichTextBox控件是一种既能够输入文本. 又能够修改文本的文字处理控件, 与TextBox控件比较, RichTextBox控件的文字处理功用更加丰厚, 不只能够设定文字的色彩. 字体, 还具 ...
- IIS 工作原理之非托管代码旅程(一)
IIS6改变 IIS6可以为每个不同的虚拟目录创建不同的程序池,这样缩小了IIS的Application Pool的颗粒度,不同的虚拟目录之间是互不影响的. IIS6(和IIS7经典模式)与IIS7集 ...
- MySQL表类型和存储引擎版本不一致解决方法
使用的是老版本的mysql客户端Navicate 8 ,mysql 服务端用的是mysql5.6的版本,在修改版本引擎的时候出现版本不对; mysql error ‘TYPE=MyISAM’ 解决办法 ...
- 循环数据forin,foreach,for of
最近一直在对数据处理,循环匹配之类的,我的mentor也已经多次指出一个问题,就是在循环里面用if去判断一个数值是否存在的时候,只要找到就要退出,这个时候就要对循环的语法提出了要求: 1.for in ...
- PyCharm5.0.2最新版破解注册激活码(图文版)
下载PyCharm http://download-cf.jetbrains.com/python/pycharm-professional-5.0.2.exe 安装PyCharm 设置激活服务器 ...
- React Native组件之ScrollView 和 StatusBar和TabBarIos
React Native中的组件ScrollView类似于iOS中的UIScrollView,其基本的使用方法和熟悉如下: /** * Sample React Native App * https: ...