logo资料库

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

第1页 / 共5页
第2页 / 共5页
第3页 / 共5页
第4页 / 共5页
第5页 / 共5页
资料共5页,全文预览结束
ucos-ii 学习笔记——信号量的原理及使用 Created on: 2012-10-7 Author: zhang bin 学习笔记 for ucos-ii PC redesigned by zhang bin 2012-10-7 versions:V-0.1 All Rights Reserved /*编写一个应用程序,其中有一个函数Fun()和两个用户任务:MyTask和YouTask。 应用程序中的两个任务都可以 调用此函数,但不能同时调用*/ #include "INCLUDES.h" #define TASK_STK_SIZE 512 /* 任务堆栈长度*/ //定义一个错误信息 ac_key; char *s1="MyTask"; char *s2="YouTask"; INT8U err; INT8U y=0; OS_EVENT *Fun_Semp; //注意,前面有一个例子2 定义了互斥信号量,定义如下 //BOOLEAN 个全局变量,来标志共享资源的访问情况 //这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未 被访问,其他的任务才可以进行访问 //注意这两个信号量的区别和使用情况 //信号量,互斥信号量 实质上就是一个标志位,是一 //声明信号量 是事件控制块ECB类型的 OS_STK OS_STK OS_STK StartTaskStk[TASK_STK_SIZE]; MyTaskStk[TASK_STK_SIZE]; YouTaskStk[TASK_STK_SIZE]; //定义任务堆栈区 void Fun(INT8U x,INT8U y); void StartTask(void *data); void MyTask(void *data); /* 声明任务 */
void YouTask(void *data); /* ********************************************************************* ************************************ * ********************************************************************* ************************************ */ void main (void) { MAIN主函数 Fun_Semp=OSSemCreate(1); //在主函数中创建信号量 返回值为创建的信号 量指针,参数是信号量的计数器的值 //用该参数对信号量计数器OSEventCnt进行初始化 //1即代表只创建一个信号量,代表信号量用于对共享资源的访问(例如,把 它当做二值信号量使用),详见P166 OSInit(); uC/OS-II */ PC_DOSSaveReturn(); DOS环境 */ PC_VectSet(uCOS, OSCtxSw); uC/OS-II的中断 */ /* 初始化 /* 保存 /* 安装 OSTaskCreate(StartTask,(void *)0, &StartTaskStk[TASK_STK_SIZE - 1], 0); // 创建起始函数 OSStart(); /* 启动多任务管理 */ } void StartTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 register */ OS_CPU_SR cpu_sr; #endif key; INT16S pdata = pdata; OS_ENTER_CRITICAL(); PC_VectSet(0x08, OSTickISR); PC_SetTickRate(OS_TICKS_PER_SEC); 中断向量 */ 钟频率 */ OS_EXIT_CRITICAL(); /* Allocate storage for CPU status /*用于退出的建*/ /* Prevent compiler warning */ /* 安装时钟 /* 设置时
OSStatInit(); 任务 */ /* 初始化统计 OSTaskCreate(MyTask,(void *)0, &MyTaskStk[TASK_STK_SIZE - 1], 1); //创 建任务函数 OSTaskCreate(YouTask,(void *)0, &YouTaskStk[TASK_STK_SIZE - 1], 2); //创 建任务函数 /* See if key has been pressed /* Yes, see if it's the ESCAPE key /* Return to /* 等待3S*/ /* Allocate storage for CPU status for (;;) { //如果恩下ESC键,则退出UC/OS-II if (PC_GetKey(&key) == TRUE) { if (key == 0x1B) { PC_DOSReturn(); */ } } OSTimeDlyHMSM(0,0,3,0); */ */ DOS } } //MyTask的函数代码 void MyTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 register */ OS_CPU_SR cpu_sr; #endif pdata = pdata; for (;;) { //err表示错误信息 /* Prevent compiler warning */ OSSemPend(Fun_Semp,0,&err); //请求信号量 参数Fun_Semp是信号 量指针 0那一项是等待时限timeout,0表示无限等待 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); /* 等待1S*/ } } void YouTask(void *pdata) { #if OS_CRITICAL_METHOD == 3 register OS_CPU_SR cpu_sr; #endif //Allocate storage for CPU status pdata=pdata; for (;;) { //请求信号量 OSSemPend(Fun_Semp,0,&err); PC_DispStr(0,++y,s2,DISP_BGND_BLACK+DISP_FGND_WHITE); Fun(7,y); OSSemPost(Fun_Semp); //调用FUN函数 //释放信号量 OSTimeDlyHMSM(0,0,2,0); //等待2s } } //公共的函数Fun的代码 void Fun(INT8U x,INT8U y) { PC_DispStr(x,y," Calling FUN()",DISP_BGND_BLACK+DISP_FGND_WHITE); //显示字符串,表示调用了 Fun函数 } //创建信号量时,用的参数为1,即Fun_Semp=OSSemCreate(1); ,只创建了一个 信号量,这种情况一般是信号量用于对 //共享资源的访问(例如,可以把它当做二值信号量使用) /* 请 求 信 号 量 函 数 OSSemPend(Fun_Semp,0,&err); Fun_Semp是信号量指针 0那一项是等待时限timeout, 0表示无限等待,err表示错误信息。 原理是每当有任务申请信号量时, (下面是由申请信号量的函数OSSemPend完成)如果信号量计数器OSEventCnt的 值大于0(即表 // 请 求 信 号 量 参 数
示还有空闲的信号量可以使用),则把 OSEventCnt减1,并使该任务继续运行,表示该任务成功申请到了一个信号量, 空闲的信号量少了一个。 如果信号量计数器OSEventCnt的值等于0,表示没有空闲的信号量可用了,那么 就将该申请的任务列入到任务等待列表OSEventTbl[] 中,而使任务处于等待状态。 (下面的功能由释放信号量的函数OSSemPost完成)如果有正在使用信号量的任 务释放了信号量,则就会在任务等待表中找出优先级最高 的等待任务,并在使它就绪后调用调度器引发一次调度。如果在任务等待列表 中已经没有等待任务了,则信号量计数器就只简单 地加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 函数 //这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步 //要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信 号量了
分享到:
收藏