//BY 简单的元清 //部分内容引用了其他博主的文章,对这些博主表示感谢,时间关系就不一一指出了。 //如有转载,请说明,谢谢 /* ********************************************************************************************************* * uC/OS-II * The Real-Time Kernel * SEMAPHORE MANAGEMENT * * (c) Copyright 1992-1998, Jean J. Labrosse, Plantation, FL * All Rights Reserved * * V2.00 * * File : OS_SEM.C * By : Jean J. Labrosse ********************************************************************************************************* */ #ifndef OS_MASTER_FILE #include "software\includes.h" #endif #if OS_SEM_EN /* ********************************************************************************************************* * ACCEPT SEMAPHORE * * Description: This function checks the semaphore to see if a resource is available or, if an event * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the * resource is not available or the event did not occur. * * Arguments : pevent is a pointer to the event control block * * Returns : > 0 if the resource is available or the event did not occur the semaphore is * decremented to obtain the resource. * == 0 if the resource is not available or the event did not occur or, * you didn't pass a pointer to a semaphore ********************************************************************************************************* */ #if OS_SEM_ACCEPT_EN > 0 //无等待地请求一个信号量 INT16U OSSemAccept (OS_EVENT *pevent) reentrant { INT16U cnt; OS_ENTER_CRITICAL(); //进入临界区 if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ OS_EXIT_CRITICAL(); return (0); //如果类型不是信号量,退出临界区返回错误码 } cnt = pevent->OSEventCnt; //读取信号量 if (cnt > 0) { /* See if resource is available */ pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */ //如果信号量不是0,计数器减一 } OS_EXIT_CRITICAL(); //退出临界区 return (cnt); //返回信号量 // /* Return semaphore count */ } #endif /*$PAGE*/ /* ********************************************************************************************************* * 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) reentrant { OS_EVENT *pevent; 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; //判断ECB块是不是空 } OS_EXIT_CRITICAL(); //退出临界区 if (pevent != (OS_EVENT *)0) { /* Get an event control block */ pevent->OSEventType = OS_EVENT_TYPE_SEM; pevent->OSEventCnt = cnt; //如果有事件发生,把类型设置为SEM,赋值 /* Set semaphore value */ OSEventWaitListInit(pevent); //添加进等待列表 } return (pevent); } /*$PAGE*/ /* ********************************************************************************************************* * PEND ON SEMAPHORE * * Description: This function waits for a semaphore. * * Arguments : pevent is a pointer to the event control block associated with the desired * semaphore. * * timeout is an optional timeout period (in clock ticks). If non-zero, your task will * wait for the resource up to the amount of time specified by this argument. * If you specify 0, however, your task will wait forever at the specified * semaphore or, until the resource becomes available (or the event occurs). * * err is a pointer to where an error message will be deposited. Possible error * messages are: * * OS_NO_ERR The call was successful and your task owns the resource * or, the event you are waiting for occurred. * OS_TIMEOUT The semaphore was not received within the specified * timeout. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore. * OS_ERR_PEND_ISR If you called this function from an ISR and the result * would lead to a suspension. * * Returns : none ********************************************************************************************************* */ //等待一个信号量 void OSSemPend (OS_EVENT *pevent, INT16U timeout, INT8U *err) reentrant { OS_ENTER_CRITICAL(); //进入临界区 if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ OS_EXIT_CRITICAL(); *err = OS_ERR_EVENT_TYPE; //如果事件的类型不是信号量,退出临界区然后返回错误码 } if (pevent->OSEventCnt > 0) { /* If sem. is positive, resource available ... */ //如果有信号发生 pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */ //数目减一 OS_EXIT_CRITICAL(); //退出临界区 *err = OS_NO_ERR; //返回错误码 } else if (OSIntNesting > 0) { /* See if called from ISR ... */ //如果有中断发生 OS_EXIT_CRITICAL(); /* ... can't PEND from an ISR */ //退出临界区 *err = OS_ERR_PEND_ISR; //返回错误码 } else { /* Otherwise, must wait until event occurs */ OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */ OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */ OSEventTaskWait(pevent); /* Suspend task until event or timeout occurs */ //赋值信号量参数给给OSTCBCur并加入等待列表 OS_EXIT_CRITICAL(); //退出临界区 OSSched(); /* Find next highest priority task ready */ //退出临界区 OS_ENTER_CRITICAL(); //进入临界区 if (OSTCBCur->OSTCBStat & OS_STAT_SEM) { /* Must have timed out if still waiting for event*/ //如果超时并存在等待任务 OSEventTO(pevent); //直接运行不再等待 OS_EXIT_CRITICAL(); //退出临界区 *err = OS_TIMEOUT; /* Indicate that didn't get event within TO */ //返回错误码 } else { OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; //OSTCBCur->OSTCBEventPtr指向空指针 OS_EXIT_CRITICAL(); *err = OS_NO_ERR; //退出临界区然后返回错误码 } } } /*$PAGE*/ /* ********************************************************************************************************* * POST TO A SEMAPHORE * * Description: This function signals a semaphore * * Arguments : pevent is a pointer to the event control block associated with the desired * semaphore. * * Returns : OS_NO_ERR The call was successful and the semaphore was signaled. * OS_SEM_OVF If the semaphore count exceeded its limit. In other words, you have * signalled the semaphore more often than you waited on it with either * OSSemAccept() or OSSemPend(). * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore ********************************************************************************************************* */ //发送信号量 INT8U OSSemPost (OS_EVENT *pevent) reentrant { OS_ENTER_CRITICAL(); //进入临界区 if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); //如果事件的类型不是信号量,退出临界区然后返回错误码 } if (pevent->OSEventGrp) { /* See if any task waiting for semaphore */ //如果有事件发生 OSEventTaskRdy(pevent, (void *)0, OS_STAT_SEM); /* Ready highest prio task waiting on event */ //把任务就绪 OS_EXIT_CRITICAL(); //退出临界区 OSSched(); /* Find highest priority task ready to run */ //进行调度 return (OS_NO_ERR); //返回错误码 } else { if (pevent->OSEventCnt < 65535) { /* Make sure semaphore will not overflow */ pevent->OSEventCnt++; /* Increment semaphore count to register event */ //如果信号量满足小于65535,pevent->OSEventCnt加加 OS_EXIT_CRITICAL(); return (OS_NO_ERR); //退出临界区然后返回错误码 } else { /* Semaphore value has reached its maximum */ OS_EXIT_CRITICAL(); //退出临界区 return (OS_SEM_OVF); } } } /* ********************************************************************************************************* * QUERY A SEMAPHORE * * Description: This function obtains information about a semaphore * * Arguments : pevent is a pointer to the event control block associated with the desired * semaphore * * pdata is a pointer to a structure that will contain information about the * semaphore. * * Returns : OS_NO_ERR The call was successful and the message was sent * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore. ********************************************************************************************************* */ #if OS_SEM_QUERY_EN > 0 INT8U OSSemQuery (OS_EVENT *pevent, OS_SEM_DATA *ppdata) reentrant { INT8U i; INT8U *psrc; INT8U *pdest; OS_ENTER_CRITICAL(); //进入临界区 if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */ OS_EXIT_CRITICAL(); return (OS_ERR_EVENT_TYPE); //如果事件的类型不是信号量,退出临界区然后返回错误码 } ppdata->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */ psrc = &pevent->OSEventTbl[0]; pdest = &ppdata->OSEventTbl[0]; for (i = 0; i < OS_EVENT_TBL_SIZE; i++) { *pdest++ = *psrc++; } ppdata->OSCnt = pevent->OSEventCnt; /* Get semaphore count */ //复制信号量的参数给ppdata OS_EXIT_CRITICAL(); //退出临界区 return (OS_NO_ERR); //返回错误码 } #endif //************************* #endif
逐字逐句解析ucos ii 源代码-》OS_SEM.C
猜你喜欢
转载自blog.csdn.net/m19930517/article/details/79259604
今日推荐
周排行