logo资料库

ucos-ii学习笔记——信号量集(事件标志组)的原理及使用.doc

第1页 / 共6页
第2页 / 共6页
第3页 / 共6页
第4页 / 共6页
第5页 / 共6页
第6页 / 共6页
资料共6页,全文预览结束
ucos-ii学习笔记——信号量集(事件标志组)的原理及使用 Created on: 2012-10-8 Author: zhang bin 学习笔记 for ucos-ii PC redesigned by zhang bin 2012-10-8 versions:V-0.1 All Rights Reserved /*设计一个有三个任务的应用程序,这三个任务分别叫做Mytask Youtask Hertask。 要求用一个信号量集来控制Mytask的运行,即任务Youtask发送一个信号,任务 Hertask 发送一个信号,当这两个任务都发了信号以后,Mytask才能运行。 */ #include "INCLUDES.h" #define TASK_STK_SIZE 512 /* 任务堆栈长度*/ OS_STK 区 */ OS_STK OS_STK OS_STK StartTaskStk[TASK_STK_SIZE]; //起始任务 /*定义任务堆栈 MyTaskStk[TASK_STK_SIZE]; YouTaskStk[TASK_STK_SIZE]; HerTaskStk[TASK_STK_SIZE]; char *s1= "Mytask is running"; char *s2= "Youtask is running"; char *s3= "Hertask is running"; INT8U err; INT8U y=0; //返回的错误信息 //字符显示位置 OS_FLAG_GRP OS_FLAG_GRP类型的指针 用标志组描述信号量集 //事件控制块用来描述信号量,消息邮箱,消息队列 *Sem_F; // 定 义 一 个 信 号 量 集 指 针 , 是 标 志 组 类 型 , void StartTask(void *data); void MyTask(void *data); /* 声明起始任务 */ /* 声明任务 */
void YouTask(void *data); void HerTask(void *data); /* 声明任务 /* 声明任务 */ */ /* ********************************************************************* ************************************ * ********************************************************************* ************************************ */ MAIN主函数 void main (void) { OSInit(); uC/OS-II */ PC_DOSSaveReturn(); DOS环境 */ PC_VectSet(uCOS, OSCtxSw); uC/OS-II的中断 */ /* 初始化 /* 保存 /* 安装 Sem_F=OSFlagCreate(0,&err); // 创 建 信 号 量 集 函 数 的 原 型 为 : OS_FLAG_GRP *OSFlagCreate(OS_FLAGS flags,INT8U *err) //其中参数OS_FLAGS flags是信号的初始值,在这里指定为0,即信号初始 值为0.参数*err是错误信息,前面已经定义了 //返回的错误信息,所以此处为&err //INT8U err; //返回值为OS_FLAG_GRP型的指针,即为创建的信号量集的标志组的指针, //前面已经定义了OS_FLAG_GRP *Sem_F; //定义一个信号量集指针 OSTaskCreate(StartTask, (void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); // 创建起始任务 OSStart(); /* 启动多任务管理 */ } /* ********************************************************************* ************************************ * ********************************************************************* ************************************ */ void StartTask(void *pdata) { STARTUP TASK
#if OS_CRITICAL_METHOD == 3 进出临界段(开关中断)使用的第三种方法*/ OS_CPU_SR cpu_sr; #endif key; INT16S pdata = pdata; OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); /* Prevent compiler warning /*用于退出的建*/ */ //进入临界段 中断向量 */ 钟频率 */ PC_SetTickRate(OS_TICKS_PER_SEC); OS_EXIT_CRITICAL(); //退出临界段 /* Allocate storage for CPU status register /* 安装时钟 /* 设置时 OSStatInit(); /* 初始化统计任务 */ OSTaskCreate(MyTask, (void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 3); //在 起始任务中创建三个任务 OSTaskCreate(YouTask, (void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 4); OSTaskCreate(HerTask, (void *)0, &HerTaskStk[TASK_STK_SIZE - 1], 5); for (;;) { //如果恩下ESC键,则退出UC/OS-II if (PC_GetKey(&key) == TRUE) { has been pressed */ if (key == 0x1B) { the ESCAPE key */ PC_DOSReturn(); */ } } OSTimeDlyHMSM(0, 0, 3, 0); DOS */ } } /* See if key /* Yes, see if it's /* Return to /* Wait 3s /*--------------------MyTask任务-------------------------*/ void MyTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 OS_CPU_SR cpu_sr; /* Allocate storage for CPU status register */ #endif pdata=pdata; for( ; ; ) {
OSFlagPend( Sem_F, (OS_FLAGS)3, //请求信号量集 //请求信号量集指针 数据3强制转化为OS_FLAGS类型的数据, //过滤器 请求第0和第1位信号 0011 这里是把 //因为过滤器和信号量集中的信号都是OS_FLAGS类型的数据 //OS_FLAG_WAIT_SET_ALL+OS_FLAG_CONSUME, //信号全是 1表示信号有效 参数OS_FLAG_CONSUME表示当 //任务等待的事件发生后,清除相应的事件标志位 OS_FLAG_WAIT_SET_ALL, //信号全是1表示信号有效 没有加 参数OS_FLAG_CONSUME,所以不会清除标志位 //等待时限,0表示无限等待 //错误信息 0, &err ); //任务MyTask在这里请求信号量集,如果请求到了信号量集,就继续 运行,下面就显示信息,如果请求不到信号量集 //MyTask就挂起,处于等待状态,只到请求到了信号量集才继续往下 运行 PC_DispStr(10,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE); // 显示信息 OSTimeDlyHMSM(0,0,2,0); //等待2s } } /*-------------------------------Youtask-------------------------------------*/ void YouTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; #endif pdata=pdata; for( ; ; ) { /* // PC_DispStr(10,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE); 显示信息 OSTimeDlyHMSM(0,0,8,0); //等待8s OSFlagPost( Sem_F, (OS_FLAGS)2, //向信号量集发信号 //发送信号量集的指针 样把2强制转化为OS_FLAGS型的数据, //因为信号为OS_FLAGS型的 //选择要发送的信号 给第1位发信号 0010 同
//信号有效的选项 信号置1 OS_FLAG_SET为 OS_FLAG_SET, 置1 OS_FLAG_CLR为置0 //错误信息 &err ); OSTimeDlyHMSM(0,0,2,0); //等待2s } } /*-------------------------------Hertask-------------------------------------*/ void HerTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 Allocate storage for CPU status register */ OS_CPU_SR cpu_sr; /* // } //因为任务MyTask请求信号量集的时候请求的是第一位和第零位,所以下面两个 任务分别发送第一位和第零位信号 //有一个问题:任务请求信号量集,得到信号后,信号量集中的对应的信号会被 清除么??从本例的运行现象来看,好像 //是没有清除,因为当第一次YouTask和HerTask运行后,间隔了8s任务MyTask才 运行,因为YouTask和HerTask都等待了8s //才向信号量集发送信号。这个显现是正常的。但是以后MyTask每间隔2s就运行 一次,没有间隔8s,等待信号量集。 //查到了:OSFlagPend()函数允许指定在任务等待的事件发生后,重新置起或是 清除相应的事件标志位。这是通过在调用 PC_DispStr(10,++y,s3,DISP_BGND_BLACK+DISP_FGND_WHITE); // 给 第 0 位 发 信 号 0001 , 把 1 强 制 转 化 为 #endif pdata=pdata; for( ; ; ) { 显示信息 OSTimeDlyHMSM(0,0,8,0); OSFlagPost( Sem_F, (OS_FLAGS)1, //向信号量集发信号 //等待8s OS_FLAGS型的 OS_FLAG_SET, &err ); //信号置1 OSTimeDlyHMSM(0,0,1,0); //等待1s }
//OSFlagPend() 函 数 时 将 一 个 常 量 OS_FLAG_CONSUME 和 参 数 wait_type 相 “加”(或者相“或”)来实现的。 //例如希望等待事件标志组的BIT0位置位,而此时事件标志组的BIT0位已经置位 了,那么如果在调用OSFlagPend()时,把参数 //wait_type加上OS_FLAG_CONSUME,就能清除这个事件标志位。如下所示:(详 细说明,参见P210) /* OSFlagPend(OSFlagMyGrp, (OS_FLAGS)0x01, FLAG_WAIT_SET_ANY+OS_FLAG_CONSUME, 0, &err); */ /* 我 把 MyTask 的 OSFlagPend() 的 wait_type 参 数 改 成 OS_FLAG_WAIT_SET_ALL+OS_FLAG_CONSUME,通过运行验证上面的说法 是 正确的。运行现象为任务MyTask会处于等待状态,知道YouTask和HerTask都发 送了消息,每次运行大概都等待8s左右 说明 MyTask 通过 OSFlagPend()函数获得信号后,相应的标志位确实是被清除了, 这就是参数 OS_FLAG_CONSUME 的作用。*/
分享到:
收藏