📄 os_mutex.c
字号:
* (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 OSMutexPend().
* 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 guarded 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 有任务在等待 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 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 guarded by the mutex.
*********************************************************************************************************
*/
#if OS_MUTEX_DEL_EN
OS_EVENT *OSMutexDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
{
#if OS_CRITICAL_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; /* ... can't DELETE from an ISR */
return (pevent);
}//不允许在ISR中调用此函数
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return ((OS_EVENT *)0);
}//非法的pevent
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return (pevent);
}//非法的事件控制块
#endif
OS_ENTER_CRITICAL();
if (pevent->OSEventGrp != 0x00) { /* See if any tasks waiting on mutex */
//是不是有任务在等待
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);
OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
//释放PIP,这两行程序书上没有
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 = 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);
OSTCBPrioTbl[pip] = (OS_TCB *)0; /* Free up the PIP */
//释放PIP
pevent->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 only 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 SEMAPHORE
*
* 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 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 owns the mutex
* OS_TIMEOUT The mutex was not available within the specified time.
* OS_ERR_EVENT_TYPE If you didn't 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
*
* 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:超时时间选项(按时钟节拍来),如果非零,任务将按照此
参数的定时在队列中等待消息到来,如果设置为零,任务将在目标
队列中永远等待,直到消息到来。
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 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
INT8U pip; /* Priority Inheritance Priority (PIP) */
//优先级继承优先级
INT8U mprio; /* Mutex owner priority */
//nutex拥有的优先级
BOOLEAN rdy; /* Flag indicating task was ready */
//显示任务就绪的标志
OS_TCB *ptcb;
if (OSIntNesting > 0) { /* See if called from ISR ... */
*err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
return;
}//不允许在ISR中调用此函数
#if OS_ARG_CHK_EN > 0
if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
*err = OS_ERR_PEVENT_NULL;
return;
}//非法的pevent
if (pevent->OSEventType != OS_EVENT_TYPE_MUTEX) { /* Validate event block type */
*err = OS_ERR_EVENT_TYPE;
return;
}//非法的事件控制块
#endif
OS_ENTER_CRITICAL(); /* Is Mutex available? */
if ((INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8) == OS_MUTEX_AVAILABLE) {//确保Mutex有效
pevent->OSEventCnt &= OS_MUTEX_KEEP_UPPER_8; /* Yes, Acquire the resource */
//如果OSEventCnt低八位是0xFF,这个mutex有效,此函数将mutex赋给任务,且
//此函数置OSEventCnt低八位是调用此函数的优先级
pevent->OSEventCnt |= OSTCBCur->OSTCBPrio; /* Save priority of owning task */
pevent->OSEventPtr = (void *)OSTCBCur; /* Point to owning task's OS_TCB */
//OSEventPtr指向调用该函数任务的任务控制块。
OS_EXIT_CRITICAL();
*err = OS_NO_ERR;
return;
}
//如果mutex不可用
pip = (INT8U)(pevent->OSEventCnt >> 8); /* No, Get PIP from mutex */
//在调用让任务进入休眠状态程序前,先提取mutex中的PIP,占用mutex任务的
//优先级和占用mutex的任务控制块指针
mprio = (INT8U)(pevent->OSEventCnt & OS_MUTEX_KEEP_LOWER_8); /* Get priority of mutex owner */
ptcb = (OS_TCB *)(pevent->OSEventPtr); /* Point to TCB of mutex owner */
//如果占用mutex的任务优先级比调用此函数的任务优先级值大(低),则要将
//占用此mutex的任务优先级提升到PIP。
if (ptcb->OSTCBPrio != pip && mprio > OSTCBCur->OSTCBPrio) { /* Need to promote prio of owner?*/
if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) { /* See if mutex owner is ready */
/* Yes, Remove owner from Rdy ...*/
//如果任务处于就绪态,那么这个任务就已不是处在它原来优先级上的就绪态,
//是以置rdy标志。表明占用mutex的任务进入就绪态。可以运行。
/* ... list at current prio */
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
rdy = TRUE;
} else {
rdy = FALSE; /* No */
}//如果任务没进入就绪态,rdy置位与否要看情况。置位是为了表明需要让这个
//任务在新的,较高的优先级PIP上进入就绪态
ptcb->OSTCBPrio = pip; /* Change owner task prio to PIP */
ptcb->OSTCBY = ptcb->OSTCBPrio >> 3;//在优先级继续优先级上处理任务控制块。
ptcb->OSTCBBitY = OSMapTbl[ptcb->OSTCBY];
ptcb->OSTCBX = ptcb->OSTCBPrio & 0x07;
ptcb->OSTCBBitX = OSMapTbl[ptcb->OSTCBX];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -