【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.用户可以创建任意个事 ...
随机推荐
- mongostat 3.2指标详解
存储引擎:wiredTiger /usr/local/mongodb-3.2.8/bin/mongostat -uroot -pcEqHuoqiJYhjVpuL --host 127.0.0.1 ...
- HTML中head里的内容经浏览器解析后全到body里
我从linux服务器nginx上把一个网站迁移到windows的IIS上数据什么的都么有问题,配置好rewrite以后,访问网站,发现样式变动了,网站上方空出了一块我用chrome浏览器的审查元素一看 ...
- hdu 1052 (greedy algorithm) 分类: hdoj 2015-06-18 16:49 35人阅读 评论(0) 收藏
thanks to http://acm.hdu.edu.cn/discuss/problem/post/reply.php?action=support&postid=19638&m ...
- 用maven搭建 testNG+PowerMock+Mockito测试框架
单元测试是开发中必不可少的一部分,是产品代码的重要保证. Junit和testNG是当前最流行的测试框架,Junit是使用最广泛的测试框架,有兴趣的话自己baidu一下. testNG基于Junit和 ...
- linux下各种软件的安装过程
//////知识储备//////////////////////////////////////////////////////////////////// /var 下存放着服务和经常改变的文件 / ...
- AMQP与RabbitMQ简介
MQ(Message Queue,消息队列)是一种应用系统之间的通信方法.是通过读写出入队列的消息来通信(RPC则是通过直接调用彼此来通信的). 1.AMQP协议 在了解RabbitMQ之前,首先要了 ...
- H5版俄罗斯方块(2)---游戏的基本框架和实现
前言: 上文中谈到了H5版俄罗斯方块的需求和目标, 这次要实现一个可玩的版本. 但饭要一口一口吃, 很多东西并非一蹴而就. 本文将简单实现一个可玩的俄罗斯方块版本. 下一步会引入AI, 最终采用coc ...
- 在线聊天室的实现(1)--websocket协议和javascript版的api
前言: 大家刚学socket编程的时候, 往往以聊天室作为学习DEMO, 实现简单且上手容易. 该Demo被不同语言实现和演绎, 网上相关资料亦不胜枚举. 以至于很多技术书籍在讲解网络相关的编程时, ...
- MXNet设计笔记之:深度学习的编程模式比较
市面上流行着各式各样的深度学习库,它们风格各异.那么这些函数库的风格在系统优化和用户体验方面又有哪些优势和缺陷呢?本文旨在于比较它们在编程模式方面的差异,讨论这些模式的基本优劣势,以及我们从中可以学到 ...
- thinkphp 内置标签volist 控制换行
thinkphp 内置标签volist 控制换行 volist标签通常用于查询数据集(select方法)的结果输出,通常模型的select方法返回的结果是一个二维数组,可以直接使用volist标签进行 ...