新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > ucos-ii学习笔记——信号量的原理及使用

ucos-ii学习笔记——信号量的原理及使用

作者:时间:2016-11-28来源:网络收藏
Createdon:2012-10-7

Author:zhangbin

本文引用地址:http://www.eepw.com.cn/article/201611/322849.htm

学习笔记

forucos-iiPC

redesignedbyzhangbin

2012-10-7

versions:V-0.1

AllRightsReserved

#include"INCLUDES.h"

#defineTASK_STK_SIZE512

char*s1="MyTask";

char*s2="YouTask";

INT8Uerr;//定义一个错误信息

INT8Uy=0;

OS_EVENT*Fun_Semp;//声明信号量是事件控制块ECB类型的

//注意,前面有一个例子2定义了互斥信号量,定义如下

//BOOLEANac_key;//信号量,互斥信号量实质上就是一个标志位,是一个全局变量,来标志共享资源的访问情况

//这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未被访问,其他的任务才可以进行访问

//注意这两个信号量的区别和使用情况

OS_STKStartTaskStk[TASK_STK_SIZE];//定义任务堆栈区

OS_STKMyTaskStk[TASK_STK_SIZE];

OS_STKYouTaskStk[TASK_STK_SIZE];

voidFun(INT8Ux,INT8Uy);

voidStartTask(void*data);

voidMyTask(void*data);

voidYouTask(void*data);

voidmain(void)

{

Fun_Semp=OSSemCreate(1);//在主函数中创建信号量返回值为创建的信号量指针,参数是信号量的计数器的值

//用该参数对信号量计数器OSEventCnt进行初始化

//1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把它当做二值信号量使用),详见P166

OSInit();

PC_DOSSaveReturn();

PC_VectSet(uCOS,OSCtxSw);

OSTaskCreate(StartTask,(void*)0,&StartTaskStk[TASK_STK_SIZE-1],0);//创建起始函数

OSStart();

}

voidStartTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

INT16Skey;

pdata=pdata;

OS_ENTER_CRITICAL();

PC_VectSet(0x08,OSTickISR);

PC_SetTickRate(OS_TICKS_PER_SEC);

OS_EXIT_CRITICAL();

OSStatInit();

OSTaskCreate(MyTask,(void*)0,&MyTaskStk[TASK_STK_SIZE-1],1);//创建任务函数

OSTaskCreate(YouTask,(void*)0,&YouTaskStk[TASK_STK_SIZE-1],2);//创建任务函数

for(;;)

{

//如果恩下ESC键,则退出UC/OS-II

if(PC_GetKey(&key)==TRUE)

{

if(key==0x1B)

{

PC_DOSReturn();

}

}

OSTimeDlyHMSM(0,0,3,0);

}

}

//MyTask的函数代码

voidMyTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3

OS_CPU_SRcpu_sr;

#endif

pdata=pdata;

for(;;)

{

OSSemPend(Fun_Semp,0,&err);//请求信号量参数Fun_Semp是信号量指针0那一项是等待时限timeout,0表示无限等待

//err表示错误信息

PC_DispStr(0,++y,s1,DISP_BGND_BLACK+DISP_FGND_WHITE);//显示MyTask字符串

Fun(7,y);//调用Fun函数

OSSemPost(Fun_Semp);//发送信号量释放信号量,函数的参数Fun_Semp代表信号量的指针

OSTimeDlyHMSM(0,0,1,0);

}

}

voidYouTask(void*pdata)

{

#ifOS_CRITICAL_METHOD==3//AllocatestorageforCPUstatusregister

OS_CPU_SRcpu_sr;

#endif

pdata=pdata;

for(;;)

{

OSSemPend(Fun_Semp,0,&err);//请求信号量

PC_DispStr(0,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE);

Fun(7,y);//调用FUN函数

OSSemPost(Fun_Semp);//释放信号量

OSTimeDlyHMSM(0,0,2,0);//等待2s

}

}

//公共的函数Fun的代码

voidFun(INT8Ux,INT8Uy)

{

PC_DispStr(x,y,"CallingFUN()",DISP_BGND_BLACK+DISP_FGND_WHITE);//显示字符串,表示调用了Fun函数

}

//创建信号量时,用的参数为1,即Fun_Semp=OSSemCreate(1);,只创建了一个信号量,这种情况一般是信号量用于对

//共享资源的访问(例如,可以把它当做二值信号量使用)

//在上面的程序中,当MyTask运行时,先请求获得了信号量,对共享资源Fun函数进行访问,由于只创建了一个信号量,

//所以在MyTask的访问期间,即使任务YouTask也进行申请信号量,此时OSEventCnt是值已经为0了,所以会把任务

//YouTask列入任务等代表OSEventTbl[]中,使任务处于等待状态。

//只有等MyTask对Fun函数访问完成了,调用OSSemPost(Fun_Semp);释放了信号量,该释放信号量的函数会先检查任务等待

//表中是否还有等待信号量的任务,如果有,则使任务进入就绪态后,调用调度器OS_Sched()引发一次任务调度,去运行等待

//任务列表中优先级最高的任务。如果没有,则就把信号量计数器OSSemCnt加1.

//所以任务YouTask要想访问Fun()函数,必须等到任务MyTask对Fun访问完毕,释放了信号量之后,才能访问,反之亦然

//所以由上面可以看出,只创建一个信号量,即OSSemCreate(1);,作用就相当于使用一个二值信号量,标志共享资源是否正在

//被访问

//看懂了上面的分析,也就可以解释实验现象了,由于YouTask等待2s,MyTask等待1s,所以有可能在MyTask访问Fan函数期间,YouTask

//也来访问(也有可能是反过来),但是由于信号量已经被MyTask占用了,所YouTask只好等待,MyTask使用完了,释放了信号量,YouTask才能正常使用Fun函数

//这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步

//要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信号量了



评论


相关推荐

技术专区

关闭