yzai的个人空间 https://passport2.21ic.com/?1197968 [收藏] [复制] [RSS] 我想永生,精神或者肉体最终接受不了时间的洗礼

日志

ucosii信号量简单快速理解

已有 554 次阅读2018-6-19 17:36 |个人分类:ucosii|系统分类:兴趣爱好

信号量简单理解

      信号量可以分为两种:一种是二值型信号量(0和1),另外一种是 N 值信号量。
      二值型信号量好比家里的座机,任何时候,只能有一个人占用。而 N 值信号量,则好比公共电话亭,可以同时有N个人排队使用。
      UCOSII 将二值型信号量称之为也叫互斥型信号量,将 N 值信号量称之为计数型信号量,也就是普通的信号量。

      下面介绍的是普通信号量

1) 创建信号量函数
    用函数 OSSemCreate 来创建一个信号量,该函数的原型为:OS_EVENT *OSSemCreate (INT16U cnt);
    其中,该函数返回值为已创建的信号量的指针,而参数 cnt 则是信号量计数器(OSEventCnt)的初始值。
    例如:sem_beep=OSSemCreate(0);//创建信号量       

2) 请求信号量函数
    任务通过调用函数 OSSemPend 请求信号量,该函数原型如下:void OSSemPend ( OS_EVENT *pevent, INT16U timeout, INT8U *err);
    其中,参数 pevent 是被请求信号量的指针, timeout 为等待时限, err 为错误信息。
    为防止任务因得不到信号量而处于长期的等待状态,函数 OSSemPend 允许用参数timeout 设置一个等待时间的限制,当任务等待的时间超过 timeout 时可以结束等待状态而进入就绪状态。如果参数 timeout 被设置为 0,则表明任务的等待时间为无限长。
    例如:OSSemPend(sem_beep,0,&err);//请求信号量    

3) 发送信号量函数
     任务获得信号量,并在访问共享资源结束以后,必须要释放信号量,释放信号量也叫做发送信号量,发送信号通过 OSSemPost 函数实现 。 OSSemPost 函数在对信号量的计数器操作之前,首先要检查是否还有等待该信号量的任务。如果没有,就把信号量计数器OSEventCnt 加一;如果有,则调用调度器 OS_Sched( )去运行等待任务中优先级别最高的任务。
     函数 OSSemPost 的原型为:INT8U OSSemPost(OS_EVENT *pevent);
     其中, pevent 为信号量指针,该函数在调用成功后,返回值为 OS_ON_ERR,否则会根据具体错误返回 OS_ERR_EVENT_TYPE、OS_SEM_OVF。
     例如:OSSemPost(sem_beep);//发送信号量       

4) 删除信号量函数
    应用程序如果不需要某个信号量了,那么可以调用函数 OSSemDel 来删除该信号量,
    该函数的原型为:OS_EVENT *OSSemDel (OS_EVENT *pevent,INT8U opt, INT8U *err);
    其中, pevent 为要删除的信号量指针, opt 为删除条件选项, err 为错误信息。

        工作机制举例说明:ucosii创建了C任务,C任务中创建了信号量sem_beep=OSSemCreate(0),则sem_beep就是信号量的指针,信号量计数器(OSEventCnt)的初始值为0,另外在C任务中又创建了A和B任务,A任务中调用了发送信号量函数OSSemPost(sem_beep),B任务中调用了请求信号量函数OSSemPend(sem_beep,0,&err),一个任务在运行状态下每调用一次发送信号量函数,则信号量计数器(OSEventCnt)的值加1,只有信号量计数器的值不为0,另一个任务在调用该信号量的请求信号量函数后才能执行,否则信号量计数器的值为0,调用请求信号量函数的任务无法执行。如果信号量计数器的值不为0,则调用请求信号量函数的任务可以执行,且每调用一次请求信号量函数则信号量计数器(OSEventCnt)的值减1,任务多次执行直至信号量计数器的值为0。即只有A任务运行后信号量计数器(OSEventCnt)的值加1,不为0,B任务才能运行,且使之减1。
      由于信号量计数器(OSEventCnt)在事件控制块结构体中定义的,且sem_beep被定义为结构体指针(OS_EVENT * sem_beep;),所以如果相要对信号量计数器(OSEventCnt)进行使用,则应表示为sem_beep->OSEventCnt,如下。

事件控制块结构体定义如下:
typedef struct os_event {
    INT8U    OSEventType;                    /* Type of event control block (see OS_EVENT_TYPE_xxxx)    */
    void    *OSEventPtr;                     /* Pointer to message or queue structure                   */
    INT16U   OSEventCnt;                     /* Semaphore Count (not used if other EVENT type)信号量计数器 */
    OS_PRIO  OSEventGrp;                     /* Group corresponding to tasks waiting for event to occur */
    OS_PRIO  OSEventTbl[OS_EVENT_TBL_SIZE];  /* List of tasks waiting for event to occur                */

#if OS_EVENT_NAME_EN > 0u
    INT8U   *OSEventName;
#endif
} OS_EVENT;


OS_EVENT * sem_beep;

if(sem_beep->OSEventCnt==0)
{

  ...
}

参考原子103zet6开发板中的ucosii实验例程



路过

鸡蛋

鲜花

握手

雷人

评论 (0 个评论)