EDABOSS电子论坛

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 828|回复: 0

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

[复制链接]

10

主题

0

回帖

20

E币

技术员

Rank: 2

积分
20
发表于 2017-3-29 17:19:50 | 显示全部楼层 |阅读模式
#include "INCLUDES.h"

#define  TASK_STK_SIZE        512                 

char *s1="MyTask";
char *s2="YouTask";
INT8U err;   //定义一个错误信息
INT8U y=0;
OS_EVENT *Fun_Semp;    //声明信号量  是事件控制块ECB类型的
//注意,前面有一个例子2 定义了互斥信号量,定义如下
//BOOLEAN   ac_key;   //信号量,互斥信号量 实质上就是一个标志位,是一个全局变量,来标志共享资源的访问情况
//这样,当已经有任务访问共享资源时,其他的任务就不能访问,知道该资源未被访问,其他的任务才可以进行访问
//注意这两个信号量的区别和使用情况

OS_STK        StartTaskStk[TASK_STK_SIZE];   //定义任务堆栈区
OS_STK        MyTaskStk[TASK_STK_SIZE];
OS_STK        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)
{
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();      
}

void  StartTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        
    OS_CPU_SR  cpu_sr;
#endif
    INT16S        key;            
    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的函数代码
void  MyTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        
    OS_CPU_SR  cpu_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);  
    }
}

void  YouTask(void *pdata)
{
#if OS_CRITICAL_METHOD == 3        //Allocate storage for CPU status register
    OS_CPU_SR  cpu_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的代码
void Fun(INT8U x,INT8U y)
{
PC_DispStr(x,y,"  Calling FUN()",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函数
//这样也就解决了多任务对共享资源的使用的问题,使任务之间得到了同步
//要仔细分析信号量工作的原理,把上面的内容看懂了,基本上也就可以使用信号量了

积分规则
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|EDABOSS电子论坛

GMT+8, 2024-4-24 05:41 , Processed in 0.036822 second(s), 20 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表