1、xilentz 的网络文摘博客园 首页 新随笔 联系 订阅 管理 随笔 - 204 文章 - 0 评论 - 10 trackbacks - 0 OS_MUTEX.C/* uC/OS-II* The Real-Time Kernel* MUTUAL EXCLUSION SEMAPHORE MANAGEMENT* (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL* All Rights Reserved* File : OS_MUTEX.C* By : Jean J. Labrosse互斥型信号量管理*/ #ifndef OS_MASTER
2、_FILE#include “includes.h“#endif /* LOCAL CONSTANTS*/ #define OS_MUTEX_KEEP_LOWER_8 0x00FF#define OS_MUTEX_KEEP_UPPER_8 0xFF00 #define OS_MUTEX_AVAILABLE 0x00FF #if OS_MUTEX_EN 0/* ACCEPT MUTUAL EXCLUSION SEMAPHORE* Description: This function checks the mutual exclusion semaphore to see if a resourc
3、e is available.* Unlike OSMutexPend(), OSMutexAccept() 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* err is a pointer to an error code which will be returned to your application:* OS_NO_ERR
4、 if the call was successful.* OS_ERR_EVENT_TYPE if pevent is not a pointer to a mutex* OS_ERR_PEVENT_NULL pevent is a NULL pointer* OS_ERR_PEND_ISR if you called this function from an ISR* Returns : = 1 if the resource is available, the mutual exclusion semaphore is acquired* = 0 a) if the resource
5、is not available* b) you didnt pass a pointer to a mutual exclusion semaphore* c) you called this function from an ISR* Warning(s) : This function CANNOT be called from an ISR because mutual exclusion semaphores are* intended to be used by tasks only.*/ #if OS_MUTEX_ACCEPT_EN 0INT8U OSMutexAccept (O
6、S_EVENT *pevent, INT8U *err)#if OS_CRITICAL_METHOD = 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr;#endif if (OSIntNesting 0) /* Make sure its not called from an ISR */*err = OS_ERR_PEND_ISR;return (0);#if OS_ARG_CHK_EN 0if (pevent = (OS_EVENT *)0) /* Validate pevent */*err = OS_E
7、RR_PEVENT_NULL;return (0);if (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Validate event block type */*err = OS_ERR_EVENT_TYPE;return (0);#endif OS_ENTER_CRITICAL(); /* Get value (0 or 1) of Mutex */if (pevent-OSEventCnt /* Mask off LSByte (Acquire Mutex) */pevent-OSEventCnt |= OSTCBCur-OSTCBPrio;
8、 /* Save current task priority in LSByte */pevent-OSEventPtr = (void *)OSTCBCur; /* Link TCB of task owning Mutex */OS_EXIT_CRITICAL();*err = OS_NO_ERR;return (1);OS_EXIT_CRITICAL();*err = OS_NO_ERR;return (0);#endif /*$PAGE*/ /* CREATE A MUTUAL EXCLUSION SEMAPHORE* Description: This function create
9、s a mutual exclusion semaphore.* Arguments : prio is the priority to use when accessing the mutual exclusion semaphore. In* other words, when the semaphore is acquired and a higher priority task* attempts to obtain the semaphore then the priority of the task owning the* semaphore is raised to this p
10、riority. It is assumed that you will specify* a priority that is LOWER in value than ANY of the tasks competing for the* mutex.* err is a pointer to an error code which will be returned to your application:* OS_NO_ERR if the call was successful.* OS_ERR_CREATE_ISR if you attempted to create a MUTEX
11、from an ISR* OS_PRIO_EXIST if a task at the priority inheritance priority* already exist.* OS_ERR_PEVENT_NULL No more event control blocks available.* OS_PRIO_INVALID if the priority you specify is higher that the * maximum allowed (i.e. OS_LOWEST_PRIO)* Returns : != (void *)0 is a pointer to the ev
12、ent control clock (OS_EVENT) associated with the* created mutex.* = (void *)0 if an error is detected.* Note(s) : 1) The LEAST significant 8 bits of .OSEventCnt are used to hold the priority number* of the task owning the mutex or 0xFF if no task owns the mutex.* 2) The MOST significant 8 bits of .O
13、SEventCnt are used to hold the priority number* to use to reduce priority inversion.建立一个互斥型信号量描述:建立一个互斥型信号量参数:prio:当存取互斥型信号量时它的优先级。就是说,当任务需要信号量,而另一优先级更高的任务想得到信号量,就改变当前任务的优先级,变为更高假定你改变的优先级值小于任务竞争这个信号量的任务的值(即优先级更高)err:应用时包含错误代码的指针 :* OS_NO_ERR 调用成功* OS_ERR_CREATE_ISR 如果想从 ISR 中建立* OS_PRIO_EXIST 如果优先级继
14、承优先级的优先级已经存在* OS_ERR_PEVENT_NULL 没有事件控制块可用* OS_PRIO_INVALID 如果你指定的优先级大于最大值 */ OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err)#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 . */*err = OS
15、_ERR_CREATE_ISR; /* . cant CREATE mutex from an ISR */return (OS_EVENT *)0);/不能从 ISR 中建立,不允许在 ISR 中调用此函数#if OS_ARG_CHK_EN 0if (prio = OS_LOWEST_PRIO) /* Validate PIP */*err = OS_PRIO_INVALID;return (OS_EVENT *)0);/不合理的 PIP#endifOS_ENTER_CRITICAL();if (OSTCBPrioTblprio != (OS_TCB *)0) /* Mutex priori
16、ty must not already exist */确认 PIP 没有被任何任务占用。 OSTCBPrioTbl 中的一个指向 NULL 的空指针指示/PIP 有效OS_EXIT_CRITICAL(); /* Task already exist at priority . */*err = OS_PRIO_EXIST; /* . inheritance priority */如果优先级存在 ,则出错。return (OS_EVENT *)0); OSTCBPrioTblprio = (OS_TCB *)1; /* Reserve the table entry */置非空指针,将这个优先
17、级保留下来。pevent = OSEventFreeList; /* Get next free event control block */从空余 ECB 中得到一块空的 ECB。if (pevent = (OS_EVENT *)0) /* See if an ECB was available */看 ECB 是否可用OSTCBPrioTblprio = (OS_TCB *)0; /* No, Release the table entry */如果不可用,释放此优先级表入口OS_EXIT_CRITICAL();*err = OS_ERR_PEVENT_NULL; /* No more e
18、vent control blocks */return (pevent);OSEventFreeList = (OS_EVENT *)OSEventFreeList-OSEventPtr; /* Adjust the free list */如果可用,重新调整事件控制块的表头OS_EXIT_CRITICAL();pevent-OSEventType = OS_EVENT_TYPE_MUTEX;/将其标记为互斥型信号量pevent-OSEventCnt = (prio OSEventPtr = (void *)0; /* No task owning the mutex */消息正在初始化,所
19、以没有等待这个 mutex 的任务OS_EventWaitListInit(pevent);/初始化事件等待列表*err = OS_NO_ERR;return (pevent); /*$PAGE*/ /* DELETE A MUTEX* Description: This function deletes a mutual exclusion semaphore and readies all tasks pending on the it.* Arguments : pevent is a pointer to the event control block associated with
20、the desired mutex.* opt determines delete options as follows:* opt = OS_DEL_NO_PEND Delete mutex ONLY if no task pending* opt = OS_DEL_ALWAYS Deletes the mutex even if tasks are waiting.* In this case, all the tasks pending will be readied.* err is a pointer to an error code that can contain one of
21、the following values:* OS_NO_ERR The call was successful and the mutex was deleted* OS_ERR_DEL_ISR If you attempted to delete the MUTEX from an ISR* OS_ERR_INVALID_OPT An invalid option was specified* OS_ERR_TASK_WAITING One or more tasks were waiting on the mutex* OS_ERR_EVENT_TYPE If you didnt pas
22、s a pointer to a mutex* OS_ERR_PEVENT_NULL If pevent is a NULL pointer.* Returns : pevent upon error* (OS_EVENT *)0 if the mutex was successfully deleted.* Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of* the mutex MUST check the return code of OSM
23、utexPend().* 2) This call can potentially disable interrupts for a long time. The interrupt disable* time is directly proportional to the number of tasks waiting on the mutex.* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the* resource(s) will no longer be g
24、uarded by the mutex.删除一个互斥型信号量描述: 删除一个互斥型信号量将挂起的任务就绪参数:pevent:指向事件控制块结合目标 mutex 的指针* opt 决定删除选项* opt = OS_DEL_NO_PEND 没有任务挂起时才删* opt = OS_DEL_ALWAYS 即使有任务挂起也删,删除后所有等待的事件全部就绪* err 指向包含错误代码的指针* OS_NO_ERR 调用成功 mutex 删除* OS_ERR_DEL_ISR 如果在 ISR 中调用此函数* OS_ERR_INVALID_OPT 设置了非法选项* OS_ERR_TASK_WAITING 有任务在
25、等待 mutex* OS_ERR_EVENT_TYPE 如果没有传递指针到 mutex* OS_ERR_PEVENT_NULL 如果 pevent 是一个空指针备注:1) 小心使用, Tasks that would normally expect the presence of* the mutex MUST check the return code of OSMutexPend().* 2) This call can potentially disable interrupts for a long time. The interrupt disable* time is direct
26、ly proportional to the number of tasks waiting on the mutex.* 3) Because ALL tasks pending on the mutex will be readied, you MUST be careful because the* resource(s) will no longer be guarded by the mutex.*/ #if OS_MUTEX_DEL_ENOS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err)#if OS_CRIT
27、ICAL_METHOD = 3 /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr;#endif BOOLEAN tasks_waiting;INT8U pip; if (OSIntNesting 0) /* See if called from ISR . */*err = OS_ERR_DEL_ISR; /* . cant DELETE from an ISR */return (pevent);/不允许在 ISR 中调用此函数#if OS_ARG_CHK_EN 0if (pevent = (OS_EVENT *)0
28、) /* Validate pevent */*err = OS_ERR_PEVENT_NULL;return (OS_EVENT *)0);/非法的 peventif (pevent-OSEventType != OS_EVENT_TYPE_MUTEX) /* Validate event block type */*err = OS_ERR_EVENT_TYPE;return (pevent);/非法的事件控制块#endifOS_ENTER_CRITICAL();if (pevent-OSEventGrp != 0x00) /* See if any tasks waiting on mu
29、tex */是不是有任务在等待tasks_waiting = TRUE; /* Yes */ else tasks_waiting = FALSE; /* No */switch (opt) /删除选项case OS_DEL_NO_PEND: /* Delete mutex only if no task waiting */无任务等待才删除if (tasks_waiting = FALSE) pip = (INT8U)(pevent-OSEventCnt 8);OSTCBPrioTblpip = (OS_TCB *)0; /* Free up the PIP */释放 PIP,这两行程序书上
30、没有pevent-OSEventType = OS_EVENT_TYPE_UNUSED;/标记为没有使用pevent-OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */OSEventFreeList = pevent;/返回 ECB 到空闲列表OS_EXIT_CRITICAL();*err = OS_NO_ERR;return (OS_EVENT *)0); /* Mutex has been deleted */ else /如果有任务在等待OS_EXIT_CRITICAL();*err =
31、OS_ERR_TASK_WAITING;return (pevent); case OS_DEL_ALWAYS: /* Always delete the mutex */如果强制删除while (pevent-OSEventGrp != 0x00) /* Ready ALL tasks waiting for mutex */OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MUTEX);/就绪所有等待任务pip = (INT8U)(pevent-OSEventCnt 8);OSTCBPrioTblpip = (OS_TCB *)0; /* Free up
32、 the PIP */释放 PIPpevent-OSEventType = OS_EVENT_TYPE_UNUSED;/标记为未用pevent-OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */OSEventFreeList = pevent; /* Get next free event control block */将 ECB 标明为没有被占用,并被送回到空余事件控制块OS_EXIT_CRITICAL();if (tasks_waiting = TRUE) /* Reschedule on
33、ly if task(s) were waiting */OS_Sched(); /* Find highest priority task ready to run */如果有任务等待,因为全部就绪,就进行任务调度。*err = OS_NO_ERR;return (OS_EVENT *)0); /* Mutex has been deleted */ default:/其它异常情况OS_EXIT_CRITICAL();*err = OS_ERR_INVALID_OPT;return (pevent);#endif /*$PAGE*/ /* PEND ON MUTUAL EXCLUSION S
34、EMAPHORE* Description: This function waits for a mutual exclusion semaphore.* Arguments : pevent is a pointer to the event control block associated with the desired* mutex.* timeout is an optional timeout period (in clock ticks). If non-zero, your task will* wait for the resource up to the amount of
35、 time specified by this argument.* If you specify 0, however, your task will wait forever at the specified* mutex or, until the resource becomes available.* 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 ow
36、ns the mutex* OS_TIMEOUT The mutex was not available within the specified time.* OS_ERR_EVENT_TYPE If you didnt pass a pointer to a mutex* OS_ERR_PEVENT_NULL pevent is a NULL pointer* OS_ERR_PEND_ISR If you called this function from an ISR and the result* would lead to a suspension.* Returns : none*
37、 Note(s) : 1) The task that owns the Mutex MUST NOT pend on any other event while it owns the mutex.* 2) You MUST NOT change the priority of the task that owns the mutex等待一个互斥型信号量描述: 等待一个互斥型信号量参数:pevent:指向事件控制块结合目标 mutex 的指针timeout:超时时间选项(按时钟节拍来),如果非零,任务将按照此参数的定时在队列中等待消息到来,如果设置为零,任务将在目标队列中永远等待,直到消息到
38、来。err:指向可能的错误消息的指针,可能为:* OS_NO_ERR 调用成功,任务接收到 mutex* OS_TIMEOUT 定时时间内 mutex 没有来* OS_ERR_EVENT_TYPE 你没有传递指针到队列* OS_ERR_PEVENT_NULL 如果 pevent 是一个空指针* OS_ERR_PEND_ISR 如果从 ISR 中调用,结果将出现异常 返回:无备注:拥有 mutex 的任务不能在拥有的同时在其它事件中挂起不能改变拥有 mutex 的信号量*/void OSMutexPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)#if OS_CRITICAL_METHOD = 3