ucos-ii 2.52信号量的小结

这里结合任哲的书籍+源代码来分析信号量
1、在任哲的书中,提到信号量只有普通的信号量,没有区分freertos所谓的二值信号量和计数信号量。可以看看源代码,ucos的代码风格是很不错的,个人认为这个风格比freertos好,看起来很舒服,不像freertos一大堆宏定义。
可以看到,OSSemCreate函数中的cnt变量如果是0,就没有资源,大于0就有资源,所以这个函数等效与freertos的二值信号量和计数信号量,一个函数就顶freertos两个函数的功能。

/*
*********************************************************************************************************
*                                           CREATE A SEMAPHORE
*
* Description: This function creates a semaphore.
*
* Arguments  : cnt           is the initial value for the semaphore.  If the value is 0, no resource is
*                            available (or no event has occurred).  You initialize the semaphore to a
*                            non-zero value to specify how many resources are available (e.g. if you have
*                            10 resources, you would initialize the semaphore to 10).
*
* Returns    : != (void *)0  is a pointer to the event control clock (OS_EVENT) associated with the
*                            created semaphore
*              == (void *)0  if no event control blocks were available
*********************************************************************************************************
*/

OS_EVENT  *OSSemCreate (INT16U cnt)
{
#if OS_CRITICAL_METHOD == 3                                /* Allocate storage for CPU status register */
    OS_CPU_SR  cpu_sr;
#endif    
    OS_EVENT  *pevent;


    if (OSIntNesting > 0) {                                /* See if called from ISR ...               */
        return ((OS_EVENT *)0);                            /* ... can't CREATE from an ISR             */
    }
    OS_ENTER_CRITICAL();
    pevent = OSEventFreeList;                              /* Get next free event control block        */
    if (OSEventFreeList != (OS_EVENT *)0) {                /* See if pool of free ECB pool was empty   */
        OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
    }
    OS_EXIT_CRITICAL();
    if (pevent != (OS_EVENT *)0) {                         /* Get an event control block               */
        pevent->OSEventType = OS_EVENT_TYPE_SEM;
        pevent->OSEventCnt  = cnt;                         /* Set semaphore value                      */
        pevent->OSEventPtr  = (void *)0;                   /* Unlink from ECB free list                */
        OS_EventWaitListInit(pevent);                      /* Initialize to 'nobody waiting' on sem.   */
    }
    return (pevent);
}

重点可以看:pevent->OSEventCnt = cnt; /* Set semaphore value */

书中也有两个实例,一个是资源共享的实例,一个是同步的实例,区别在于初始化信号量的初始值是不一样的,前者是OSSemCreate(1),后者是OSSemCreate(0)。

请求信号量函数,函数原型:void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
可以看出参数中,OS_EVENT *pevent,是最重要的,如果有信号量,就会pevent->OSEventCnt--,没有就一直等待,或者等待一段时间

发送信号量函数
INT8U OSSemPost (OS_EVENT *pevent)
看得出来,参数很简单,只有一个事件的结构体指针,可以看到下面的核心语句:

    if (pevent->OSEventCnt < 65535) {                 /* Make sure semaphore will not overflow         */
        pevent->OSEventCnt++;                         /* Increment semaphore count to register event   */
        OS_EXIT_CRITICAL();
        return (OS_NO_ERR);
    }

说明,信号量是uint16类型的,发送信号量会执行pevent->OSEventCnt++

总结,就是ucos ii 2.52的代码比较易读,他的信号量已经包括了freertos的两个信号量,根据初始值不同而有所区别,其本质就是一个计数信号量的功能。

原文地址:https://www.cnblogs.com/CodeWorkerLiMing/p/12252213.html