zoukankan      html  css  js  c++  java
  • ocos 信号量

    信号量分为  :声明信号量、互斥信号量

    转:  

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

     

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

    #include "INCLUDES.h"

    #define  TASK_STK_SIZE        512                 

       

    char *s1="MyTask";

    char *s2="YouTask";

    INT8U err;   //定义一个错误信息

    INT8U y=0;

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

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

    //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那一项是等待时限timeout0表示无限等待

         //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[]中,使任务处于等待状态。

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

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

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

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

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

    //被访问

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

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

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

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

  • 相关阅读:
    C语言程序设计第5堂作业
    C语言程序设计第4堂作业
    gets和fgets函数的区别
    编写一个程序实现strcpy函数的功能
    编写一个程序实现strcmp函数的功能
    编写一个程序实现strcat函数的功能
    11-1. 通讯录的录入与显示(10)
    11-0. 平面向量加法(10)
    10-4. 字符串循环左移(20)
    10-3. 字符串逆序(15)
  • 原文地址:https://www.cnblogs.com/locean/p/5314757.html
Copyright © 2011-2022 走看看