定位到uCOS-II/Source/os_mutex.c,该文件是互斥型信号量的相关操作函数。互斥型信号量也就是互斥锁Mutex,是一个二值(0/1)信号量。在操作共享资源时,使用Mutex可以保证满足互斥条件。
1. 非阻塞的获取互斥型信号量函数OSMutexAccept()
OSMutexAccept()用于检测Mutex以判断是否可用,若资源不可用,调用此函数不会使得所在任务被挂起。
//允许使用os中的Mutex
#if OS_MUTEX_ACCEPT_EN > 0u
BOOLEAN OSMutexAccept (OS_EVENT *pevent, //pevent指向管理着某资源的Mutex,
INT8U *perr) //perr为输出型参数用于表示出错类型
{
INT8U pcp;
//临界区保护方法3
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION(); //与系统异常相关,找不到定义,不细究
return (OS_FALSE);
}
#endif
//检测参数宏使能
#if OS_ARG_CHK_EN > 0u
if (pevent == (OS_EVENT *)0) {
*perr = OS_ERR_PEVENT_NULL;
return (OS_FALSE);
}
#endif
//本函数是支持MUTEX的,若非OS_EVENT_TYPE_MUTEX,返回错误
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) {
*perr = OS_ERR_EVENT_TYPE;
return (OS_FALSE);
}
//不能再ISR中试图获取二值信号量
if (OSIntNesting > 0u) {
*perr = OS_ERR_PEND_ISR;
return (OS_FALSE);
}
//进入临界区
OS_ENTER_CRITICAL();
//高8位为天花板优先级,其优先等级大于所有可以获取该Mutex的任务的优先级
pcp = (INT8U)(pevent->OSEventCnt >> 8u);
//低8位全为1表示该Mutex没有被任务获取过,Mutex可用
if ((pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {
//将天花板优先级设置到pevent->OSEventCnt,其实这句话不起效果,
//pevent->OSEventCnt本来就为天花板优先级
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8;
//将任务优先级设置到低8位,以表示该互斥锁被任务获取了
pevent->OSEventCnt |= OSTCBCur->OSTCBPrio;
//将事件控制块连接到该任务控制块
pevent->OSEventPtr = (void *)OSTCBCur;
if ((pcp != OS_PRIO_MUTEX_CEIL_DIS) && //OS_PRIO_MUTEX_CEIL_DIS表示禁用将优先级提升天花板
(OSTCBCur->OSTCBPrio <= pcp)) { //天花板的优先级必须不小于获取该Mutex的任务,否则说明在创建Mutex的时候
//天花板优先级设置出错
OS_EXIT_CRITICAL();
*perr = OS_ERR_PCP_LOWER;
} else {
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE; //正常执行
}
return (OS_TRUE);
}
OS_EXIT_CRITICAL();
*perr = OS_ERR_NONE;
return (OS_FALSE);
}
#endif
2. 创建和初始化互斥型信号量函数OSMutexCreate()
互斥型信号量mutual的建立和初始化. 在操作共享资源时, 使用Mutex可以保证满足互斥条件。
OS_EVENT *OSMutexCreate (INT8U prio, //用于设置Mutex的天花板优先级
INT8U *perr) //用于输出错误信息
{
OS_EVENT *pevent;
#if OS_CRITICAL_METHOD == 3u
OS_CPU_SR cpu_sr = 0u;
#endif
#ifdef OS_SAFETY_CRITICAL
if (perr == (INT8U *)0) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_EVENT *)0);
}
#endif
#ifdef OS_SAFETY_CRITICAL_IEC61508
if (OSSafetyCriticalStartFlag == OS_TRUE) {
OS_SAFETY_CRITICAL_EXCEPTION();
return ((OS_EVENT *)0);
}
#endif
#if OS_ARG_CHK_EN > 0u
if (prio != OS_PRIO_MUTEX_CEIL_DIS) { //OS_PRIO_MUTEX_CEIL_DIS表禁用将优先级提升天花板
if (prio >= OS_LOWEST_PRIO) { //prio大于OS_LOWEST_PRIO,非法
*perr = OS_ERR_PRIO_INVALID;
return ((OS_EVENT *)0);
}
}
#endif
if (OSIntNesting > 0u) {
*perr = OS_ERR_CREATE_ISR;
return ((OS_EVENT *)0);
}
OS_ENTER_CRITICAL();
if (prio != OS_PRIO_MUTEX_CEIL_DIS) {
//判断天花板优先级对应的任务是否存在,不等于0表示存在
if (OSTCBPrioTbl[prio] != (OS_TCB *)0) {
OS_EXIT_CRITICAL();
*perr = OS_ERR_PRIO_EXIST;
return ((OS_EVENT *)0);
}
//不存在则天花