事件标志是一个用来实现同步的对象,由多个位组成,用作指示对应事件存在的标志。事件标志由用来指示对应事件存在的位模式(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. javascript内置属性——arguments

    arguments是javascript中的内置属性,可以直接调用函数的参数,作用类似Array,但本身并不是数组.这次发现它是为了实现封装函数,将不确定数量的数字乘积.比如function mult ...

  2. Code Simplicity–The Science of Software Development 书摘

    Chapter1 Introduction That is the art and talent involved in programming—reducing complexity to simp ...

  3. shell中&&和||的使用方法

    测试题: [ -z "" ] && echo 0 || echo 1 的结果是多少 看看这两个 && || 的用户  http://blog.csd ...

  4. i++问题

    例题,以下代码的输出结果是什么? #include <stdio.h> int main() { ,,,,}; int *ptr = arr; *(ptr++) += ; printf(& ...

  5. SSM框架学习之高并发秒杀业务--笔记1-- 项目的创建和依赖

    在慕课网上看了Java高并发秒杀API视屏后,觉得这个案例真的让我学到了很多,现在重新自己实现一遍,博客记下,顺便分析其中的要点. 第一步是项目的创建和依赖 利用Maven去创建工程然后导入Idea中 ...

  6. ECSHOP 优化 ecshop错误转向地址更改

    原有的ECSHOP,在一些产品找不到或者被删除的情况下,亦或是直接对动态页面的访问,在参数丢失或者数据库找不到匹配数据时,程序处理是指向首页的,这样不利于优化,需对一些页面的程序进行修改,如:good ...

  7. 定时调度框架Quartz随笔

    最近项目中的定时批处理用到了quartz定时任务,在此记录下quartz的配置吧,一个小demo仅供参考,也方便自己今后复习! 下面直接来步骤吧! 一.首先,要搭起能让quartz正常运行的环境,至少 ...

  8. Android Studio项目目录结构

    在Android Studio中,提供了以下几种项目结构类型 我们一般常用的有以下两种结构: Project 结构类型 app/build/ app模块build编译输出的目录 app/build.g ...

  9. Android 自动生成表格

    Layout.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:a ...

  10. Linq一 基础知识

    1.什么是Linq 他是VS2008(.net framework 3.5)之后一项重大的突破 全程Lnaguage Integrated Query,可以成为数据迭代器. 主要有以下5大块组成: L ...